使用JSch库进行SFTP连接

2023-10-22 15:17:38 浏览数 (2)

使用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);

0 人点赞