How to use apache vfs2 for sftp with public-private-key and without password
Solution 1
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;
}
}
Solution 2
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)
.
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);
Comments
-
LStrike almost 2 years
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; }
-
Imran Jawaid about 6 yearsCan you provide the file you have for keyPath ? should it need to have only private key or both private and public keys ?? Like i have a ppk file which has lots of stuff. Should i provide path to that file here or what ? @woddle
-
tony over 2 yearsIf we don't use the method to create the connection string, how do we handle the remote file, what do we pass in as the uri: FileObject remoteFile = sysManager.resolveFile(?, fileOptions).