1. 概述

SSHJ 是一个开源的 Java 库,通过 SSH 协议实现与远程服务器的安全通信。

本文将介绍 SSHJ 库的核心功能和使用方法,帮助开发者快速掌握这个强大的工具。

2. 依赖配置

使用 SSHJ 库前,需要在项目中添加以下 Maven 依赖:

<dependency>
    <groupId>com.hierynomus</groupId>
    <artifactId>sshj</artifactId>
    <version>0.38.0</version>
</dependency>

最新版本可在 Maven 中央仓库 查询。

3. SSHJ 核心功能

SSHJ 库主要用于建立 SSH 安全连接,支持以下核心功能:

文件传输:通过 SCP 或 SFTP 协议上传/下载文件
端口转发:支持本地端口转发和远程端口转发
远程命令执行:在服务器上执行任意命令
连接管理:提供连接状态监控和保活机制

4. 建立 SSH 连接

SSHJ 支持两种认证方式:密码认证和公钥认证。

4.1. 密码认证

通过密码连接服务器需要指定主机、端口、用户名和密码:

String host = "192.168.1.100";
int port = 22;
String username = "admin";
String password = "securePassword123";

SSHClient client = new SSHClient();
client.addHostKeyVerifier(new PromiscuousVerifier());
client.connect(host, port);
client.authPassword(username, password);

⚠️ 注意PromiscuousVerifier 会跳过主机密钥验证,生产环境应使用更安全的验证方式。

4.2. 公钥认证

使用公钥认证前,需确保:

  1. 客户端生成密钥对
  2. 公钥已添加到服务器的 authorized_keys 文件
String host = "192.168.1.100";
String username = "admin";
File privateKeyFile = new File("/home/user/.ssh/id_rsa");
int port = 22;

SSHClient client = new SSHClient();
KeyProvider privateKey = client.loadKeys(privateKeyFile.getPath());
client.addHostKeyVerifier(new PromiscuousVerifier());
client.connect(host, port);
client.authPublickey(username, privateKey);

5. 执行远程命令

通过 SSHJ 执行远程命令非常简单:

SSHClient sshClient = new SSHClient();
// ...(连接代码省略)

Session session = sshClient.startSession();
Command cmd = session.exec("ls -lsa");
BufferedReader reader = new BufferedReader(new InputStreamReader(cmd.getInputStream()));
String line;
while ((line = reader.readLine()) != null) {
    System.out.println(line);
}
cmd.join(5, TimeUnit.SECONDS);
session.close();

关键点

  • 使用 BufferedReader 读取命令输出
  • join() 方法设置命令超时时间
  • 执行完毕后务必关闭会话

6. SCP 文件传输

SCP(Secure Copy)提供简单的文件传输方案。

6.1. 文件上传

String filePath = "/local/path/file.txt";

SSHClient ssh = new SSHClient();
// ...(连接代码省略)
ssh.useCompression(); // 启用压缩提升传输速度
ssh.newSCPFileTransfer()
  .upload(new FileSystemFile(filePath), "/remote/upload/");

性能优化useCompression() 启用 zlib 压缩,大文件传输时效果显著。

6.2. 文件下载

String downloadPath = "/local/download/";
String fileName = "remote_file.txt";

SSHClient ssh = new SSHClient();
// ...(连接代码省略)
ssh.useCompression();
ssh.newSCPFileTransfer()
  .download("/remote/upload/" + fileName, downloadPath);

7. SFTP 文件传输

SFTP(SSH File Transfer Protocol)提供更丰富的文件操作功能。

7.1. 文件上传

String filePath = "/local/path/file.txt";

SSHClient ssh = new SSHClient();
// ...(连接代码省略)
SFTPClient sftp = ssh.newSFTPClient();
sftp.put(new FileSystemFile(filePath), "/remote/upload/");
sftp.close();

7.2. 文件下载

String downloadPath = "/local/download/";
String fileName = "remote_file.txt";

SSHClient ssh = new SSHClient();
// ...(连接代码省略)
SFTPClient sftp = ssh.newSFTPClient();
sftp.get("/remote/upload/" + fileName, downloadPath);
sftp.close();

优势:SFTP 支持目录操作、文件权限管理等高级功能。

8. 本地端口转发

将远程服务端口映射到本地,实现安全访问:

SSHClient ssh = new SSHClient();
// ...(连接代码省略)

Parameters params = new Parameters(
    ssh.getRemoteHostname(),  // 远程主机
    8081,                     // 本地端口
    "internal-service.com",   // 目标主机
    80                        // 目标端口
);

ServerSocket ss = new ServerSocket();
ss.setReuseAddress(true);
ss.bind(new InetSocketAddress(params.getLocalHost(), params.getLocalPort()));
ssh.newLocalPortForwarder(params, ss).listen();

🔧 应用场景:安全访问内网服务,如数据库、管理后台等。

9. 远程端口转发

将本地服务暴露给远程服务器网络:

SSHClient ssh = new SSHClient();
// ...(连接代码省略)

ssh.getConnection()
  .getKeepAlive()
  .setKeepAliveInterval(5); // 保活间隔

ssh.getRemotePortForwarder()
  .bind(
    new Forward(8083), // 远程端口
    new SocketForwardingConnectListener(
      new InetSocketAddress("localhost", 8080) // 本地服务
    )
  );

ssh.getTransport().join(); // 保持连接

⚠️ 注意:需确保防火墙允许相应端口的访问。

10. 连接状态监控

通过 KeepAlive 机制检测连接状态:

String hostName = "192.168.1.100";
String userName = "admin";
String password = "securePassword123";

DefaultConfig defaultConfig = new DefaultConfig();
defaultConfig.setKeepAliveProvider(KeepAliveProvider.KEEP_ALIVE);

SSHClient ssh = new SSHClient(defaultConfig);
ssh.addHostKeyVerifier(new PromiscuousVerifier());
ssh.connect(hostName, 22);

ssh.getConnection()
  .getKeepAlive()
  .setKeepAliveInterval(5); // 5秒保活间隔

ssh.authPassword(userName, password);

// 示例:长时间运行的任务
Session session = ssh.startSession();
session.allocateDefaultPTY();
new CountDownLatch(1).await(); // 模拟长时间任务
session.close();
ssh.disconnect();

关键配置

  • KeepAliveProvider.KEEP_ALIVE 启用保活机制
  • setKeepAliveInterval() 设置保活间隔(建议 5-30 秒)

11. 总结

SSHJ 是一个功能全面的 Java SSH 客户端库,主要优势包括:

多种认证方式:密码/公钥认证灵活切换
双协议文件传输:SCP 简单高效,SFTP 功能丰富
端口转发能力:支持本地/远程端口转发
连接管理完善:提供保活机制和状态监控

对于需要 SSH 功能的 Java 项目,SSHJ 是一个值得考虑的解决方案。本文所有示例代码可在 GitHub 获取。


原始标题:Introduction to SSHJ | Baeldung