INT-1614 refactored SftpSession and DefaultSftpSessionFactory to align with Ftp
This commit is contained in:
@@ -22,6 +22,9 @@ import org.springframework.integration.file.remote.session.SessionFactory;
|
||||
import org.springframework.util.Assert;
|
||||
import org.springframework.util.StringUtils;
|
||||
|
||||
import com.jcraft.jsch.JSch;
|
||||
import com.jcraft.jsch.UserInfo;
|
||||
|
||||
/**
|
||||
* Factory for creating {@link SftpSession} instances.
|
||||
*
|
||||
@@ -44,8 +47,10 @@ public class DefaultSftpSessionFactory implements SessionFactory {
|
||||
private volatile Resource privateKey;
|
||||
|
||||
private volatile String privateKeyPassphrase;
|
||||
|
||||
private final JSch jsch = new JSch();;
|
||||
|
||||
|
||||
|
||||
public void setHost(String host) {
|
||||
this.host = host;
|
||||
}
|
||||
@@ -80,19 +85,81 @@ public class DefaultSftpSessionFactory implements SessionFactory {
|
||||
Assert.isTrue(this.port >= 0, "port must be a positive number");
|
||||
Assert.isTrue(StringUtils.hasText(this.password) || privateKey != null || StringUtils.hasText(this.privateKeyPassphrase),
|
||||
"either a password or a private key and/or a private key passphrase is required");
|
||||
String privateKeyToPass = null;
|
||||
try {
|
||||
if (privateKey != null){
|
||||
privateKeyToPass = privateKey.getFile().getAbsolutePath();
|
||||
}
|
||||
SftpSession session = new SftpSession(
|
||||
this.user, this.host, this.password, this.port, this.knownHosts, null, privateKeyToPass, this.privateKeyPassphrase);
|
||||
session.connect();
|
||||
return session;
|
||||
|
||||
com.jcraft.jsch.Session jschSession = this.initJschSession();
|
||||
SftpSession sftpSession = new SftpSession(jschSession);
|
||||
sftpSession.connect();
|
||||
return sftpSession;
|
||||
}
|
||||
catch (Exception e) {
|
||||
throw new IllegalStateException("failed to create SFTP Session", e);
|
||||
}
|
||||
}
|
||||
|
||||
private com.jcraft.jsch.Session initJschSession() throws Exception {
|
||||
|
||||
if (port <= 0) {
|
||||
port = 22;
|
||||
}
|
||||
|
||||
|
||||
if (StringUtils.hasText(this.knownHosts)) {
|
||||
this.jsch.setKnownHosts(this.knownHosts);
|
||||
}
|
||||
|
||||
// private key
|
||||
String privateKeyFilePath = this.privateKey.getFile().getAbsolutePath();
|
||||
if (privateKey != null) {
|
||||
if (StringUtils.hasText(privateKeyPassphrase)) {
|
||||
this.jsch.addIdentity(privateKeyFilePath, privateKeyPassphrase);
|
||||
}
|
||||
else {
|
||||
this.jsch.addIdentity(privateKeyFilePath);
|
||||
}
|
||||
}
|
||||
com.jcraft.jsch.Session jsSession = this.jsch.getSession(this.user, this.host, this.port);
|
||||
if (StringUtils.hasText(this.password)) {
|
||||
jsSession.setPassword(this.password);
|
||||
}
|
||||
jsSession.setUserInfo(new OptimisticUserInfoImpl(this.password));
|
||||
return jsSession;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* this is a simple, optimistic implementation of this interface. It simply returns in the positive where possible
|
||||
* and handles interactive authentication (ie, 'Please enter your password: ' prompts are dispatched automatically using this)
|
||||
*/
|
||||
private static class OptimisticUserInfoImpl implements UserInfo {
|
||||
|
||||
private String password;
|
||||
|
||||
public OptimisticUserInfoImpl(String password) {
|
||||
this.password = password;
|
||||
}
|
||||
|
||||
public String getPassphrase() {
|
||||
return null; // pass
|
||||
}
|
||||
|
||||
public String getPassword() {
|
||||
return password;
|
||||
}
|
||||
|
||||
public boolean promptPassphrase(String string) {
|
||||
return true;
|
||||
}
|
||||
|
||||
public boolean promptPassword(String string) {
|
||||
return true;
|
||||
}
|
||||
|
||||
public boolean promptYesNo(String string) {
|
||||
return true;
|
||||
}
|
||||
|
||||
public void showMessage(String string) {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -24,14 +24,11 @@ import org.apache.commons.logging.LogFactory;
|
||||
|
||||
import org.springframework.integration.file.remote.session.Session;
|
||||
import org.springframework.util.Assert;
|
||||
import org.springframework.util.StringUtils;
|
||||
|
||||
import com.jcraft.jsch.ChannelSftp;
|
||||
import com.jcraft.jsch.ChannelSftp.LsEntry;
|
||||
import com.jcraft.jsch.JSch;
|
||||
import com.jcraft.jsch.JSchException;
|
||||
import com.jcraft.jsch.SftpException;
|
||||
import com.jcraft.jsch.UserInfo;
|
||||
|
||||
/**
|
||||
* Default SftpSession implementation.
|
||||
@@ -41,7 +38,7 @@ import com.jcraft.jsch.UserInfo;
|
||||
* @author Mark Fisher
|
||||
* @since 2.0
|
||||
*/
|
||||
public class SftpSession implements Session {
|
||||
class SftpSession implements Session {
|
||||
|
||||
private final Log logger = LogFactory.getLog(this.getClass());
|
||||
|
||||
@@ -49,66 +46,9 @@ public class SftpSession implements Session {
|
||||
|
||||
private final com.jcraft.jsch.Session jschSession;
|
||||
|
||||
private String privateKey;
|
||||
|
||||
private String privateKeyPassphrase;
|
||||
|
||||
private volatile UserInfo userInfo;
|
||||
|
||||
|
||||
/**
|
||||
* @param userName the name of the account being logged into.
|
||||
* @param hostName this should be the host. I found values like <code>foo.com</code> work, where
|
||||
* <code>http://foo.com</code> don't.
|
||||
* @param userPassword if you are not using key based authentication, then you are likely being prompted
|
||||
* for a password each time you login. This is that password. It is <em>not</em> the
|
||||
* passphrase for the private key!
|
||||
* @param port the default is 22, and if you specify N<0 for this value we'll default it to 22
|
||||
* @param knownHostsFile this is the known hosts file. If you don't specify it, jsch does some magic to work
|
||||
* without your specification. If you have it in a non well-known location, however,
|
||||
* this property is for you. An example: <code>/home/user/.ssh/known_hosts</code>
|
||||
* @param knownHostsInputStream this is the known hosts file. If you don't specify it, jsch does some magic to work
|
||||
* without your specification. If you have it in a non well-known location, however,
|
||||
* this property is for you. An example: <code>/home/user/.ssh/known_hosts</code>. Note
|
||||
* that you may specify this <em>or</em> the #knownHostsFile - not both!
|
||||
* @param privateKey this is usually used when you want passwordless automation (obviously, for this
|
||||
* integration it's useless since this lets you specify a password once, anyway, but
|
||||
* still good to have if required). This file might be ~/.ssh/id_dsa, or a
|
||||
* <code>.pem</code> for your remote server (for example, on EC2)
|
||||
* @param pvKeyPassPhrase sometimes, to be extra secure, the private key itself is extra encrypted. In order
|
||||
* to surmount that, we need the private key passphrase. Specify that here.
|
||||
* @throws Exception thrown if any of a myriad of scenarios plays out
|
||||
*/
|
||||
public SftpSession(String userName, String hostName, String userPassword, int port, String knownHostsFile,
|
||||
InputStream knownHostsInputStream, String privateKey, String pvKeyPassPhrase) throws Exception {
|
||||
|
||||
JSch jSch = new JSch();
|
||||
if (port <= 0) {
|
||||
port = 22;
|
||||
}
|
||||
this.privateKey = privateKey;
|
||||
this.privateKeyPassphrase = pvKeyPassPhrase;
|
||||
if (StringUtils.hasText(knownHostsFile)) {
|
||||
jSch.setKnownHosts(knownHostsFile);
|
||||
}
|
||||
else if (knownHostsInputStream != null) {
|
||||
jSch.setKnownHosts(knownHostsInputStream);
|
||||
}
|
||||
// private key
|
||||
if (privateKey != null) {
|
||||
if (StringUtils.hasText(privateKeyPassphrase)) {
|
||||
jSch.addIdentity(this.privateKey, privateKeyPassphrase);
|
||||
}
|
||||
else {
|
||||
jSch.addIdentity(this.privateKey);
|
||||
}
|
||||
}
|
||||
this.jschSession = jSch.getSession(userName, hostName, port);
|
||||
if (StringUtils.hasText(userPassword)) {
|
||||
this.jschSession.setPassword(userPassword);
|
||||
}
|
||||
this.userInfo = new OptimisticUserInfoImpl(userPassword);
|
||||
this.jschSession.setUserInfo(userInfo);
|
||||
public SftpSession(com.jcraft.jsch.Session jschSession){
|
||||
this.jschSession = jschSession;
|
||||
}
|
||||
|
||||
void connect() {
|
||||
@@ -207,42 +147,4 @@ public class SftpSession implements Session {
|
||||
jschSession.disconnect();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* this is a simple, optimistic implementation of this interface. It simply returns in the positive where possible
|
||||
* and handles interactive authentication (ie, 'Please enter your password: ' prompts are dispatched automatically using this)
|
||||
*/
|
||||
private static class OptimisticUserInfoImpl implements UserInfo {
|
||||
|
||||
private String password;
|
||||
|
||||
public OptimisticUserInfoImpl(String password) {
|
||||
this.password = password;
|
||||
}
|
||||
|
||||
public String getPassphrase() {
|
||||
return null; // pass
|
||||
}
|
||||
|
||||
public String getPassword() {
|
||||
return password;
|
||||
}
|
||||
|
||||
public boolean promptPassphrase(String string) {
|
||||
return true;
|
||||
}
|
||||
|
||||
public boolean promptPassword(String string) {
|
||||
return true;
|
||||
}
|
||||
|
||||
public boolean promptYesNo(String string) {
|
||||
return true;
|
||||
}
|
||||
|
||||
public void showMessage(String string) {
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user