今天要做一个功能:用sftp协议传文件到远程服务器,服务器是别人配置的,给出账号密码和端口2888。用的库是jsch,版本0.1.50。
根据jsch的示例,很快就改出一个实现:
import com.jcraft.jsch.Channel;
import com.jcraft.jsch.ChannelSftp;
import com.jcraft.jsch.JSch;
import com.jcraft.jsch.JSchException;
import com.jcraft.jsch.Session;
import com.jcraft.jsch.SftpException;
import com.jcraft.jsch.UserInfo;
public class Sftp {
private static Session getSession(String user, String passwd, String host,
int port) throws JSchException {
UserInfo ui = new MyUserInfo(passwd);
JSch jsch = new JSch();
Session session = jsch.getSession(user, host, port);
session.setUserInfo(ui);
session.connect();
return session;
}
private static ChannelSftp getFtpChannel(Session session)
throws JSchException {
Channel channel = session.openChannel( "sftp" );
channel.connect();
ChannelSftp c = (ChannelSftp) channel;
return c;
}
public static boolean putFile(String user, String passwd, String host,
int port, String localeFile, String remoteFile) {
Session session = null ;
ChannelSftp channel = null ;
try {
session = getSession(user, passwd, host, port);
channel = getFtpChannel(session);
channel.put(localeFile, remoteFile, ChannelSftp. OVERWRITE);
channel.quit();
} catch (JSchException e) {
e.printStackTrace();
return false ;
} catch (SftpException e) {
e.printStackTrace();
return false ;
} finally {
clear(session, channel);
}
return true ;
}
private static void clear(Session session, Channel channel) {
if (channel != null) {
channel.disconnect();
}
if (session != null) {
session.disconnect();
}
}
public static void main(String[] arg) {
boolean b = Sftp.putFile( "user" , "passwd" , "host" , 2888, "localeFile" ,
"remoteFile" );
System. out .println(b);
}
public static class MyUserInfo implements UserInfo {
final String passwd ;
public MyUserInfo(String passwd) {
this .passwd = passwd;
}
public String getPassword() {
return passwd ;
}
public boolean promptYesNo(String str) {
// step 1, confirm accept host
return true ; // 接受任意服务器的指纹
}
public String getPassphrase() {
return null ;
}
public boolean promptPassphrase(String message) {
return true ;
}
public boolean promptPassword(String message) {
// step 2
return true ;
}
public void showMessage(String message) {
}
}
}
拿自己的VPS linux测试下,上传是OK的。但是上传到测试服务器时却老是出错,在建立会话时总是抛出异常:com.jcraft.jsch.JSchException : Auth fail
。
一开始怀疑是账号有问题,但在Xftp下是可以登录的。在shell的sftp命令下显示指定oPort
和oPasswordAuthentication
选项也可以登录,所以就不像是账号问题了。
无奈继续google,发现很多网上代码都指定StrictHostKeyChecking
选项为no
,就把代码改为下面这样:
private static Session getSession(String user, String passwd, String host,
int port) throws JSchException {
JSch jsch = new JSch();
Session session = jsch.getSession(user, host, port);
session.setConfig( "StrictHostKeyChecking" , "no" ); // 不验证host-key,验证会失败。
session.setPassword(passwd);
session.connect();
return session;
}
还真行了。
这个问题其实是因为jsch进行严格的 SSH 公钥检查导致的,禁用 SSH 远程主机的公钥检查可以方便进行自动化任务执行。如果是在shell命令行下进行的自动化任务,建议采用客户端公钥认证,也就是ssh自动登录的方式。
欢迎关注我的微信公众号: coderbee笔记,可以更及时回复你的讨论。