使用JSch库进行SFTP连接
一、概述
JSch是一个Java库,用于实现SSH2协议。JSch可以用于连接SSH服务器并进行各种远程操作,如文件传输、端口转发、远程执行命令等。
JSch可在Linux、Unix、Windows和其他平台上运行,并且与各种Java环境兼容,包括J2SE、J2EE、Android等。
JSch提供了一组接口和类,以及许多示例代码,使得连接SSH服务器非常容易。它还支持密码和密钥交换认证,并提供了丰富的错误处理机制。使用JSch,开发人员可以轻松地在Java应用程序中实现SSH连接和远程操作。
JSch是一个开源库,由JCraft开发和维护。官方网站(http://www.jcraft.com/jsch/)
连接SFTP服务器并进行文件传输,可以使用JSch库来实现。
二、JSch的使用
2.1 用户名密码方式
下面是使用用户名密码方式连接的一个示例:
代码语言:javascript复制package cn.pomit.ftp;
import com.jcraft.jsch.*;
import java.util.Properties;
public class TestFtp {
public static String userName = "app";
public static String password = "app";
public static String ip = "127.0.0.1";
public static void main(String asdp[]){
try {
// 定义本地文件路径和远程文件路径
String localFilePath = "/path/to/local/file.txt";
String remoteFilePath = "/path/to/remote/file.txt";
ChannelSftp sftpChannel = getUserPasswordChannel();
// 将本地文件上传到SFTP服务器上
sftpChannel.put(localFilePath, remoteFilePath);
// 从SFTP服务器上下载文件到本地
sftpChannel.get(remoteFilePath, localFilePath);
// 关闭SFTP连接
sftpChannel.disconnect();
}catch (SftpException e) {
e.printStackTrace();
}
}
public static ChannelSftp getUserPasswordChannel(){
try {
JSch jsch = new JSch();
Session sshSession = jsch.getSession(userName, ip, 22);
sshSession.setPassword(password);
Properties sshConfig = new Properties();
// 设置第一次登录时自动接受SSH服务器的公钥
sshConfig.put("StrictHostKeyChecking", "no");
sshSession.setConfig(sshConfig);
sshSession.connect();
ChannelSftp channel = (ChannelSftp) sshSession.openChannel("sftp");
channel.connect();
return channel;
} catch (JSchException e) {
throw new RuntimeException("连接sfpt失败", e);
}
}
}
使用密码的方式,会因为密码变化无法使用,还可以使用公私钥方式进行链接。
2.2 密钥方式
如果要使用密钥方式进行SFTP连接,需要将RSA私钥添加到JSch中,而不是设置用户名和密码。下面是一个示例代码,演示如何使用JSch连接到SFTP服务器并使用RSA密钥进行认证:
代码语言:javascript复制package cn.pomit.ftp;
import com.jcraft.jsch.*;
import java.util.Properties;
public class TestFtp {
public static String userName = "app";
public static String ip = "127.0.0.1";
public static String priKeyBasePath = "";
public static void main(String asdp[]){
try {
// 定义本地文件路径和远程文件路径
String localFilePath = "/local/file.txt";
String remoteFilePath = "/remote/file.txt";
ChannelSftp sftpChannel = getUserPriKeyChannel();
// 将本地文件上传到SFTP服务器上
sftpChannel.put(localFilePath, remoteFilePath);
// 从SFTP服务器上下载文件到本地
sftpChannel.get(remoteFilePath, localFilePath);
// 关闭SFTP连接
sftpChannel.disconnect();
}catch (SftpException e) {
e.printStackTrace();
}
}
public static ChannelSftp getUserPriKeyChannel(String asd[]){
try {
JSch jsch = new JSch();
jsch.addIdentity(priKeyBasePath);
Session sshSession = jsch.getSession(userName, ip, 22);
Properties sshConfig = new Properties();
// 设置第一次登录时自动接受SSH服务器的公钥
sshConfig.put("StrictHostKeyChecking", "no");
sshSession.setConfig(sshConfig);
sshSession.connect();
ChannelSftp channel = (ChannelSftp) sshSession.openChannel("sftp");
channel.connect();
return channel;
} catch (JSchException e) {
throw new RuntimeException("连接sfpt失败", e);
}
}
}
三、使用方式升华
上面介绍了如何使用JSch库进行sftp的连接。但如果使用频繁,我们常常考虑使用连接池来管理连接。
apache提供了一个通用的连接池GenericObjectPool,可以进行连接管理。而构造GenericObjectPool需要一个PooledObjectFactory和一个GenericObjectPoolConfig(可以使用默认配置)。
所以,我们可以造一个Factory实现PooledObjectFactory:
3.1 Sftp工厂
SftpFactory:
代码语言:javascript复制package cn.pomit.ftp;
import lombok.Data;
import com.jcraft.jsch.ChannelSftp;
import com.jcraft.jsch.JSch;
import com.jcraft.jsch.JSchException;
import com.jcraft.jsch.Session;
import org.apache.commons.pool2.BasePooledObjectFactory;
import org.apache.commons.pool2.PooledObject;
import org.apache.commons.pool2.impl.DefaultPooledObject;
import java.util.Properties;
@Data
public class SftpFactory extends BasePooledObjectFactory<ChannelSftp> {
private FtpConfig properties;
public SftpFactory(FtpConfig properties) {
this.properties = properties;
}
/**
* 创建连接
* @return ChannelSftp
*/
@Override
public ChannelSftp create() {
return getUserPasswordChannel();
}
public ChannelSftp getUserPasswordChannel(){
try {
JSch jsch = new JSch();
Session sshSession = jsch.getSession(properties.getUserName(), properties.getIp(), properties.getPort());
sshSession.setPassword(properties.getPassword());
Properties sshConfig = new Properties();
// 设置第一次登录时自动接受SSH服务器的公钥
sshConfig.put("StrictHostKeyChecking", "no");
sshSession.setConfig(sshConfig);
sshSession.connect();
ChannelSftp channel = (ChannelSftp) sshSession.openChannel("sftp");
channel.connect();
return channel;
} catch (JSchException e) {
throw new RuntimeException("连接sfpt失败", e);
}
}
public ChannelSftp getUserPriKeyChannel(){
try {
JSch jsch = new JSch();
jsch.addIdentity(properties.getPriKeyBasePath());
Session sshSession = jsch.getSession(properties.getUserName(), properties.getIp(), properties.getPort());
Properties sshConfig = new Properties();
// 设置第一次登录时自动接受SSH服务器的公钥
sshConfig.put("StrictHostKeyChecking", "no");
sshSession.setConfig(sshConfig);
sshSession.connect();
ChannelSftp channel = (ChannelSftp) sshSession.openChannel("sftp");
channel.connect();
return channel;
} catch (JSchException e) {
throw new RuntimeException("连接sfpt失败", e);
}
}
@Override
public PooledObject<ChannelSftp> wrap(ChannelSftp channelSftp) {
return new DefaultPooledObject<>(channelSftp);
}
// 销毁对象
@Override
public void destroyObject(PooledObject<ChannelSftp> p) {
ChannelSftp channelSftp = p.getObject();
channelSftp.disconnect();
}
}
这里,SftpFactory继承了BasePooledObjectFactory,也就实现了PooledObjectFactory。提供了生成ChannelSftp的方式。
3.2 Ftp密钥及连接池
里面用到了一个FtpConfig,是配置密钥、连接池参数的,代码如下: FtpConfig:
代码语言:javascript复制package cn.pomit.ftp;
import lombok.Data;
import org.apache.commons.pool2.impl.GenericObjectPoolConfig;
/**
* @author yangshengwen
* @description FtpConfig
* @since 2021/6/3 15:14
**/
@Data
public class FtpConfig {
/**
* ip地址
*/
private String ip;
/**
* 端口号
*/
private int port;
/**
* 账号
*/
private String userName;
/**
* 密码
*/
private String password;
/**
* 操作目录
*/
private String path;
/**
* 操作目录下存放项目的目录
*/
private String projectPath;
/**
* 数据探索功能存放Csv文件目录
*/
private String projectPathCsv;
/**
* 操作目录下存放临时文件的目录
*/
private String publicPath;
/**
* 操作目录下存放模型训练多版本程序目录
*/
private String programsPath;
/**
* 操作目录下存放模型预测多版本程序目录
*/
private String programsPrdPath;
/**
* 创建文件夹
*/
private String createDirectory;
/**
* 私钥文件地址
*/
private String priKeyBasePath;
private Pool pool;
@Data
public static class Pool extends GenericObjectPoolConfig {
/**
* 对象最大数量
*/
private int maxTotal ;
/**
* 最大空闲对象数量
*/
private int maxIdle ;
/**
* 最小空闲对象数量
*/
private int minIdle ;
/**
* 当池耗尽时,阻塞的最长时间,为负值时无限等待
*/
private long maxWaitMillis;
/**
* 从池中取出对象是是否检测可用
*/
private boolean testOnBorrow;
/**
* 将对象返还给池时检测是否可用
*/
private boolean testOnReturn;
/**
* 检查连接池对象是否可用
*/
private boolean testWhileIdle;
}
}
3.3 Sftp连接池使用
代码语言:javascript复制 FtpConfig config = new FtpConfig();
//这里config需要set一些参数。
SftpFactory sftpFactory = new SftpFactory(config);
GenericObjectPool<ChannelSftp> pool = new GenericObjectPool<>(sftpFactory, sftpFactory.getProperties().getPool());
ChannelSftp channelSftp = pool.borrowObject();
// 将本地文件上传到SFTP服务器上
sftpChannel.put(localFilePath, remoteFilePath);
// 从SFTP服务器上下载文件到本地
sftpChannel.get(remoteFilePath, localFilePath);
// 归还SFTP连接
pool.returnObject(channelSftp);