SFTP ProxyCommand не работает с Apache Commons VFS - PullRequest
0 голосов
/ 08 ноября 2018

Мы хотим загрузить файл из SFTP, используя Apache Commons VFS за прокси-сервером. Наше Java-приложение должно подключаться к SFTP-серверу через прокси-сервер SOCKS5. Команда сети проверила настройки прокси на сервере sftp с помощью этой команды:

sftp -v -o ProxyCommand='nc -v -x proxyserver:1080 %h %p' the_sftp_host

Что касается этой команды, мы пытаемся использовать потоковый прокси, предоставляемый Apache Commons VFS, как указано в проблеме "[SFTP] Stream (например, netcat) прокси для файловой системы Sftp (также известной как ProxyCommand)" в https://issues.apache.org/jira/browse/VFS-440).

Использование только типа прокси SOCKS5 не работает.

Наш код основан на коде SftpProviderTestCase, предоставленном commons.apache.org в https://commons.apache.org/proper/commons-vfs/commons-vfs2/xref-test/org/apache/commons/vfs2/provider/sftp/test/SftpProviderTestCase.html

Код ниже работает без прокси. Как только мы включаем потоковый прокси-сервер, он всегда генерирует исключение, например " Не удалось подключиться к SFTP-серверу " без каких-либо дополнительных подробностей.

Зависимости Java:

  • Обще-VFS-2,1
  • JSch-0.1.53

Для прокси-сервера commons-vfs Stream требуются имя пользователя и пароль для прокси. Использование того же пользователя и пароля с сервера sftp не работает.

Итак, что нам не хватает, чтобы заставить работать потоковый прокси?

Код

package es.application.test;

import java.io.InputStream;
import java.net.URI;
import java.net.URISyntaxException;

import org.apache.commons.io.IOUtils;
import org.apache.commons.lang.StringUtils;
import org.apache.commons.lang.exception.ExceptionUtils;
import org.apache.commons.vfs2.FileObject;
import org.apache.commons.vfs2.FileSystemOptions;
import org.apache.commons.vfs2.impl.DefaultFileSystemManager;
import org.apache.commons.vfs2.provider.sftp.SftpFileSystemConfigBuilder;
import org.apache.commons.vfs2.provider.sftp.TrustEveryoneUserInfo;

import es.application.common.util.Utils;

/**
 * 
 * This code is based on https://commons.apache.org/proper/commons-vfs/commons-vfs2/xref-test/org/apache/commons/vfs2/provider/sftp/test/SftpProviderTestCase.html
 * 
 * Apache Commons VFS allows ProxyCommand as per https://issues.apache.org/jira/browse/VFS-440
 * 
 * 
 *
 */
public class ReadFromSftp {

    private String host = "sftp_host";
    private String user = "sftp_user";
    private String password = "sftp_password";
    private String remoteDir = "/";
    private String sftpileName = "the_file.xml";

    private int proxyPort=1080;     
    private String proxyHost="localhost";
    private String proxyCommand;
    private boolean useProxy = true;


    public  String readFromSFTP() {

          proxyPort=1080;
          proxyHost="proxyserver";
          useProxy = true;
          proxyCommand ="nc -X 5 -x proxyserver:1080 "+this.host+ " 22";

        String fileContent = StringUtils.EMPTY;

        if (StringUtils.isNotBlank(host)) {
            //FileSystemManager fsManager = null;
            DefaultFileSystemManager fsManager = null;
            FileSystemOptions opts = null;
            FileObject[] remoteFiles = null;
            String filePath = StringUtils.EMPTY;

            try {

                filePath = "sftp://" +host + remoteDir;
                /**
                 *  Not using fsManager = VFS.getManager();
                */
                fsManager = new DefaultFileSystemManager();

                fsManager.addProvider("sftp", new org.apache.commons.vfs2.provider.sftp.SftpFileProvider());
                fsManager.init();


                //Not using UserAuthenticator auth = new StaticUserAuthenticator(null, this.user, this.password);
                opts = new FileSystemOptions();


                /**
                 * Not using any of these configurations
                 * 
                DefaultFileSystemConfigBuilder.getInstance().setUserAuthenticator(opts, auth);
                DefaultFileSystemConfigBuilder.getInstance().setRootURI(opts, filePath);
                // FtpFileSystemConfigBuilder.getInstance().setUserDirIsRoot(opts, true);
                 */


                final SftpFileSystemConfigBuilder builder = SftpFileSystemConfigBuilder.getInstance();
                builder.setStrictHostKeyChecking(opts, "no");
                builder.setUserInfo(opts, new TrustEveryoneUserInfo());
                builder.setTimeout(opts, 20000);
                //TODO: Do we need this?
                //builder.setIdentityRepositoryFactory(fileSystemOptions, new TestIdentityRepositoryFactory());


                FileSystemOptions proxy_opts = (FileSystemOptions)opts.clone();

                if (this.useProxy) {
                    System.out.println("PROXY enabled");
                    builder.setProxyHost(opts, this.proxyHost);
                    builder.setProxyPort(opts, this.proxyPort);

                        builder.setProxyType(opts, SftpFileSystemConfigBuilder.PROXY_STREAM);
                        builder.setProxyCommand(opts, this.proxyCommand);   

                        //if this is not set, NullPointerException is thrown
                        builder.setProxyUser(opts, user);

                        //if this is not set, NullPointerException is thrown
                        builder.setProxyPassword(opts, password);

                        builder.setProxyOptions(opts, proxy_opts);
                }


                String uri = getSftpFileUri(remoteDir).toString();
                System.out.println(("URI to resolve is:"+uri));


                //
                // TODO In Based on SftpProviderTestCase.html a new URI is set, but 
                //
                // - is just for the test case? 
                // - Or is this rewrite really required? 
                // uri = String.format("sftp://%s@localhost:%d", initializeUserInfo("what_user_here", "what_password_here"), 22);
                //
                //System.out.println(("NEW URI to resolve is:"+uri));

                FileObject fo = fsManager.resolveFile(uri, opts);

                remoteFiles = fo.findFiles(Utils.getFileSelector(sftpileName));


                if (remoteFiles != null && remoteFiles.length > 0) {
                    InputStream inputStream = remoteFiles[0].getContent().getInputStream();
                    fileContent = IOUtils.toString(inputStream, "UTF-8");
                }
            } catch (Exception ex) {
                System.out.println("Exception.message: " + ex.getMessage());
                String stacktrace = ExceptionUtils.getStackTrace(ex);
                System.out.println("stacktrace.message: " + stacktrace);
            } finally {
                if (remoteFiles != null && remoteFiles.length > 0) {
                    fsManager.closeFileSystem(remoteFiles[0].getFileSystem());
                }
            }
        }

        return fileContent;
    }

    // Based on https://commons.apache.org/proper/commons-vfs/commons-vfs2/xref-test/org/apache/commons/vfs2/provider/sftp/test/SftpProviderTestCase.html
     private String initializeUserInfo(String user, String password)
        {
            String userInfo = user;

                userInfo += ":" + password;

            return userInfo;
        }

     //Based on https://commons.apache.org/proper/commons-vfs/commons-vfs2/xref-test/org/apache/commons/vfs2/provider/sftp/test/SftpProviderTestCase.html
     private URI getSftpFileUri(String remoteFilePath) throws Exception
        {
            try {
                return new URI("sftp", initializeUserInfo(this.user, this.password), host, 22, remoteFilePath, null, null);
            }
            catch (URISyntaxException e) {
                String message = String.format("URISyntaxException was thrown: Illegal character in sftp://%s:******@%s:%s%s", user, host, 22, remoteFilePath);
                throw new Exception(message);
            }
        }


    public static void main(String[] args) {

        ReadFromSftp r = new ReadFromSftp();
        String object = r.readFromSFTP();
        System.out.println(object.length());

    }

}
...