【问题标题】:How to use apache vfs2 for sftp with public-private-key and without password如何使用 apache vfs2 进行 sftp 公私钥和无密码
【发布时间】:2015-04-10 09:43:34
【问题描述】:

目前我正在使用 apache vfs2 从 sftp 下载文件。对于身份验证,我使用用户名和密码。

有没有办法只使用公私钥而不使用密码来使用 vfs2?

我想我已经使用了这个功能,但是如何使用呢?只设置为“是”?

SftpFileSystemConfigBuilder.getInstance().setStrictHostKeyChecking(options, "no");

这是我当前的代码(sn-p):

private boolean downloadFile(){

    StandardFileSystemManager sysManager = new StandardFileSystemManager();

    //download der Datei
    try {
        sysManager.init();

        FileObject localFile = sysManager.resolveFile(localFilePath);

        FileObject remoteFile = sysManager.resolveFile(createConnectionString(host, user, password, fileName, port),createDefaultOptions());

        //Selectors.SELECT_FILES --> A FileSelector that selects only the base file/folder.
        localFile.copyFrom(remoteFile, Selectors.SELECT_FILES);


    } catch (Exception e) {
        logger.error("Downloading file failed: " + e.toString());
        return false;
    }finally{
        sysManager.close();
    }
    return true;
}

private FileSystemOptions createDefaultOptions() throws FileSystemException{

    //create options for sftp
    FileSystemOptions options = new FileSystemOptions();
    //ssh key
    SftpFileSystemConfigBuilder.getInstance().setStrictHostKeyChecking(options, "no");
    //set root directory to user home
    SftpFileSystemConfigBuilder.getInstance().setUserDirIsRoot(options, true);
    //timeout
    SftpFileSystemConfigBuilder.getInstance().setTimeout(options, timeout);

    return options;
}

【问题讨论】:

  • 嘿,我们只需要在文件中提供私钥还是同时提供两个密钥??

标签: java sftp public-key-encryption apache-commons-vfs


【解决方案1】:

我们不应该使用下面的方法来创建连接字符串。这可能会暴露密码。

public static String createConnectionString(String hostName, String username, String password, String keyPath, String passphrase, String remoteFilePath) {

    if (keyPath != null) {
        return "sftp://" + username + "@" + hostName + "/" + remoteFilePath;
    } else {
        return "sftp://" + username + ":" + password + "@" + hostName + "/" + remoteFilePath;
    }
}

根据 Apache 网站上提供的文档,我们应该使用

StaticUserAuthenticator auth = new StaticUserAuthenticator("domain", "username", "password");

链接:https://commons.apache.org/proper/commons-vfs/api.html

另外,如果我们使用基于公钥或私钥的身份验证,那么我们应该使用setIdentityInfo(FileSystemOptions, IdentityInfo...) 而不是setIdentities(FileSystemOptions opts, File... identityFiles)

参考:https://commons.apache.org/proper/commons-vfs/commons-vfs2/apidocs/org/apache/commons/vfs2/provider/sftp/SftpFileSystemConfigBuilder.html

FileSystemOptions opts = new FileSystemOptions();
SftpFileSystemConfigBuilder.getInstance().setStrictHostKeyChecking(opts, "no");
SftpFileSystemConfigBuilder.getInstance().setUserDirIsRoot(opts, false);

String openSSHPrivateKey = "C:\\Users\\<filepath>\\id_rsa.key";

IdentityInfo myIdentityInfo = new IdentityInfo(new File(openSSHPrivateKey));
    
SftpFileSystemConfigBuilder.getInstance(). setIdentityInfo(opts, myIdentityInfo);

【讨论】:

    【解决方案2】:

    获取您的代码并将其包装成一个可运行的示例。注意IdentityInfo 实现。这可以通过更改明显的行来使用带有密码的密钥。

    $ javac -cp 'jsch-0.1.51.jar;commons-vfs2-2.0.jar' SftpGet.java
    $ java -cp 'jsch-0.1.51.jar;commons-vfs2-2.0.jar;commons-logging-1.1.1.jar;.' SftpGet
    

    import java.io.File;
    
    import com.jcraft.jsch.UserInfo;
    
    import org.apache.commons.vfs2.FileObject;
    import org.apache.commons.vfs2.FileSystemException;
    import org.apache.commons.vfs2.FileSystemManager;
    import org.apache.commons.vfs2.FileSystemOptions;
    import org.apache.commons.vfs2.Selectors;
    import org.apache.commons.vfs2.impl.StandardFileSystemManager;
    import org.apache.commons.vfs2.provider.sftp.SftpFileSystemConfigBuilder;
    import org.apache.commons.vfs2.provider.sftp.IdentityInfo;
    
    
        public class SftpGet {
    
            public static void main(String[] args) {
                downloadFile();
            }
    
    
            private static boolean downloadFile(){
    
                String host = "HOSTNAMEHERE";
                String user = "USERNAMEHERE";
                String password = "";
                String fileName = "/lines.txt";
                String localFilePath = "c:/cygwin64/home/woddle/wrote_lines.txt";
    
                // without passphrase
                String keyPath = "c:/cygwin64/home/woddle/.ssh/id_dsa_nopass";
                String passphrase = null;
    
                // with passphrase
                // String keyPath = "c:/cygwin64/home/woddle/.ssh/id_dsa_withpass";
                // String passphrase = "super-secrets";
    
                StandardFileSystemManager sysManager = new StandardFileSystemManager();
    
                //download der Datei
                try {
                    sysManager.init();
    
                    FileObject localFile = sysManager.resolveFile(localFilePath);
    
                    FileObject remoteFile = sysManager.resolveFile(createConnectionString(host, user, password, keyPath, passphrase, fileName), createDefaultOptions(keyPath, passphrase));
    
                    //Selectors.SELECT_FILES --> A FileSelector that selects only the base file/folder.
                    localFile.copyFrom(remoteFile, Selectors.SELECT_FILES);
    
    
                } catch (Exception e) {
                    System.out.println("Downloading file failed: " + e.toString());
                    return false;
                }finally{
                    sysManager.close();
                }
                return true;
            }
    
    
            public static String createConnectionString(String hostName, String username, String password, String keyPath, String passphrase, String remoteFilePath) {
    
                if (keyPath != null) {
                    return "sftp://" + username + "@" + hostName + "/" + remoteFilePath;
                } else {
                    return "sftp://" + username + ":" + password + "@" + hostName + "/" + remoteFilePath;
                }
            }
    
    
    
            private static FileSystemOptions createDefaultOptions(final String keyPath, final String passphrase) throws FileSystemException{
    
                //create options for sftp
                FileSystemOptions options = new FileSystemOptions();
                //ssh key
                SftpFileSystemConfigBuilder.getInstance().setStrictHostKeyChecking(options, "no");
                //set root directory to user home
                SftpFileSystemConfigBuilder.getInstance().setUserDirIsRoot(options, true);
                //timeout
                SftpFileSystemConfigBuilder.getInstance().setTimeout(options, 10000);
    
                if (keyPath != null) {
                    IdentityInfo identityInfo = null;
                    if(passPhrase!=null){
                        identityInfo = new IdentityInfo(new File(keyPath), passPhrase.getBytes());
                    }else{
                        identityInfo =  new IdentityInfo(new File(keyPath));
                    }
              SftpFileSystemConfigBuilder.getInstance().setIdentityInfo(options, identityInfo);
                }
    
    
                return options;
            }
    
    
        }
    

    【讨论】:

    • 您能提供您拥有的 keyPath 文件吗?它应该只需要私钥还是私钥和公钥都需要?就像我有一个 ppk 文件,里面有很多东西。我应该在这里提供该文件的路径还是什么? @woddle
    猜你喜欢
    • 1970-01-01
    • 2013-10-08
    • 1970-01-01
    • 2023-02-08
    • 1970-01-01
    • 1970-01-01
    • 2023-01-02
    • 2022-06-15
    • 2019-06-26
    相关资源
    最近更新 更多