SSHJ是一个开源 Java 库,它使用SSH协议与远程服务器进行安全通信。
在本文中,我们将介绍 SSHJ 库的基本功能。
依赖关系
要使用 SSHJ 库,我们必须将以下依赖项添加到项目中:
<dependency> <groupId>com.hierynomus</groupId> <artifactId>sshj</artifactId> <version>0.38.0</version> </dependency>
|
我们可以在 Maven Central 中找到最新版本的SSHJ库。SSHJ库
SSHJ 库帮助通过 SSH 建立与远程服务器的安全连接。
借助SSHJ 库,我们可以使用 SCP 或 SFTP 协议处理文件上传和下载。另外,我们还有一个额外的好处,那就是能够使用它进行本地端口转发和远程端口转发。
连接SSH客户端
SSH 客户端可以使用密码或公钥身份验证连接到服务器。 SSHJ 库使我们能够使用任一方法登录。
1.密码认证
我们可以使用 SSHJ 库通过 SSH 端口连接到服务器。需要为 SSH 连接指定主机名、端口、用户名和密码。
SSH 客户端使用authPassword()方法通过密码身份验证连接到服务器:
String host = // ... int port = // ... String username = // ... String password = // ... SSHClient client = new SSHClient(); client.addHostKeyVerifier(new PromiscuousVerifier()); client.connect(host, port); client.authPassword(username, password);
|
正如我们在上面的代码中看到的,我们使用密码身份验证将客户端连接到主机。2.公钥认证
我们也可以使用公钥连接到服务器。为了使用公钥进行连接,我们需要在服务器上的known_hosts文件中有一个文件条目,或者我们可以在客户端计算机上为远程服务器生成一个公钥,并将公钥复制到服务器上的授权SSH密钥中。
SSH 客户端使用authPublickey()方法通过公钥身份验证连接到服务器:
String host = // ... String username = // ... File privateKeyFile = // ... int port = // ... SSHClient client = new SSHClient(); KeyProvider privateKey = client.loadKeys(privateKeyFile.getPath()); client.addHostKeyVerifier(new PromiscuousVerifier()); client.connect(host, port); client.authPublickey(username, privateKey);
|
我们可以为客户端生成一个公钥,并在要连接的服务器上更新它。在其余示例中,我们将使用第一种方法登录,即使用用户名和密码。通过 SSH 执行命令
我们可以在连接到服务器的sshClient 启动的会话 上使用exec()方法通过 SSHJ 库执行命令:
SSHClient client = 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();
|
正如我们在上面的代码中看到的,我们为sshClient启动一个会话。然后,我们执行ls -lsa命令,该命令列出了目录中的所有文件。然后,我们使用BufferedReader来读取所执行命令的输出。同样,这里也可以执行其他命令。
通过SCP上传/下载文件
我们可以通过SCP上传文件。对于上传,我们使用SCPFileTransfer对象的upload()方法:
String filePath = // ... SSHClient ssh = new SSHClient(); ssh.useCompression(); ssh.newSCPFileTransfer() .upload(new FileSystemFile(filePath), "/upload/");
|
在这里,我们将文件传输到服务器上的上传目录。useCompression()方法将zlib压缩添加到首选算法中,这可以显着提高速度。无法保证谈判会成功。如果客户端已经连接,则重新协商;否则,它只会返回。我们也可以在连接客户端之前使用useCompression() 。
对于 SCP 文件下载,我们在SCPFileTransfer对象上使用download() 方法:
String downloadPath = // ... String fileName = // ... SSHClient ssh = new SSHClient(); ssh.useCompression(); ssh.newSCPFileTransfer() .download("/upload/" + fileName, downloadPath);
|
在这里,我们将文件从服务器上的upload目录下载到客户端上的downloadPath位置。上述上传和下载方法在内部运行scp命令,使用 SSH 连接将文件从本地计算机复制到远程服务器,反之亦然。
通过SFTP上传/下载文件
我们可以通过SFTP上传文件。对于上传,我们使用SFTPClient对象上的put()方法:
String filePath = // ... SSHClient ssh = new SSHClient(); SFTPClient sftp = ssh.newSFTPClient(); sftp.put(new FileSystemFile(filePath), "/upload/");
|
这里,我们将文件从客户端上的用户主目录传输到服务器上的上传目录。对于 SFTP 下载,我们使用SFTPClient对象上的get() 方法:
String downloadPath = // ... String fileName = // ... SSHClient ssh = new SSHClient(); SFTPClient sftp = ssh.newSFTPClient(); sftp.get("/upload/" + fileName, downloadPath); sftp.close();
|
在这里,我们将文件从服务器上的upload目录下载到客户端上的downloadPath位置。本地端口转发
本地端口转发用于访问远程服务器上的服务,就像服务在客户端上运行一样:
SSHClient ssh = new SSHClient(); Parameters params = new Parameters(ssh.getRemoteHostname(), 8081, "google.com", 80); ServerSocket ss = new ServerSocket(); ss.setReuseAddress(true); ss.bind(new InetSocketAddress(params.getLocalHost(), params.getLocalPort())); ssh.newLocalPortForwarder(params, ss) .listen();
|
在这里,我们将服务器的80端口转发到客户端计算机的8081端口,以便我们可以从客户端计算机上的8081端口访问服务器80端口上托管的网站或服务。远程端口转发
使用远程端口转发,我们可以将客户端计算机上运行的服务公开到远程服务器网络:
SSHClient ssh = new SSHClient(); ssh.getConnection() .getKeepAlive() .setKeepAliveInterval(5); ssh.getRemotePortForwarder() .bind(new Forward(8083), new SocketForwardingConnectListener(new InetSocketAddress("google.com", 80))); ssh.getTransport() .join();
|
这里,我们将运行在客户端8083端口的服务转发到远程服务器的80端口。实际上,在客户端计算机上的8083端口上运行的服务暴露在远程服务器的80端口上。对于本地和远程端口转发,我们需要确保正确的防火墙设置到位。
检查连接丢失
我们需要检查连接丢失以监控服务器连接状态和健康状况。 SSHJ 提供了使用 keepalive 检查连接丢失的选项:
String hostName = // ... String userName = // ... String password = // ... 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); ssh.authPassword(userName, password); Session session = ssh.startSession(); session.allocateDefaultPTY(); new CountDownLatch(1).await(); session.allocateDefaultPTY(); session.close(); ssh.disconnect();
|
在上面的代码中,我们可以看到配置KeepAliveProvider.KEEP_ALIVE启用了SSHJ库的保活模式。我们使用setKeepAliveInterval()来设置来自客户端的两个保持活动消息之间的间隔。