Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to use apache vfs2 for sftp with public-private-key and without password

Currently I am using apache vfs2 to download files from a sftp. For authentication I use user-name and password.

Is there a way to use vfs2 only with public-private-keys and without a password?

I think I have use this function,but how? Set it only to "yes"?

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

This is my current code (snippet):

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;
}

and

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;
}
like image 323
LStrike Avatar asked Feb 10 '15 11:02

LStrike


2 Answers

Taking your code and wrapping it into a runnable example. Notice the IdentityInfo implementation. This can work with a key-with-passphrase by changing the obvious lines.

$ 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

with

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;
        }


    }
like image 58
woddle Avatar answered Oct 28 '22 21:10

woddle


We should not use below method for creating the connection string. This may expose the password.

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;
    }
}

As per the documentation available on the Apache website, we should use

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

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

Also, if we are using public key or private key based authentication, then we should use setIdentityInfo(FileSystemOptions, IdentityInfo...) instead of setIdentities(FileSystemOptions opts, File... identityFiles).

Reference: 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);
like image 39
Anilns Avatar answered Oct 28 '22 20:10

Anilns