<返回更多

SSHJ - 功能齐全的Java SSH库

2020-07-19    
加入收藏

SSH(Secure Shell,安全外壳协议),是专为远程登录会话和其他网络服务提供安全性的应用层协议。在日常开发中,包括登录远程服务器、远程执行命令脚本、文件传输等,都使用了 SSH 协议的实现。而 SSHJ 就是 SSH 协议的一个 JAVA 语言实现,其功能齐全,对 SSH 协议的特性实现全面,可以很方便地在代码中实现 SSH 相关功能应用,值得 Java 开发者了解使用。

SSHJ - 功能齐全的Java SSH库

SSH协议

简介

SSHJ 是 hierynomus 在 Github 上开源的 Java SSH 库,项目位于 https://github.com/hierynomus/sshj,目前版本为 v0.29.0。

SSHJ 功能齐全,支持从 known_hosts 文件读取验证公钥,支持公钥、密码和交互式的验证方式,支持命令、子系统和 Shell Channel,支持本地和远程端口转发,支持 SCP 安全拷贝协议,支持从版本 0 到 3 的完全的 SFTP 安全文件传输协议,支持广泛的加密、签名、压缩等的算法实现。

SSHJ - 功能齐全的Java SSH库

SSH协议和SSHJ库

安装

SSHJ 使用方便,可以使用 Maven 添加到项目依赖,在 pom.xml 中添加

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

SSHJ 的主要依赖是 SLF4J,另外,一些加密算法可能会需要 BouncyCastle,而 zlib 压缩则需要依赖 JZlib。

SSHJ 也可以自行编译,需要 Java6 及以上环境,并安装有 Unlimited strength Java Cryptography Extensions (JCE) 加密扩展包,运行命令

./gradlew clean build
SSHJ - 功能齐全的Java SSH库

SSH协议与SSHJ库

实例

SSHJ中的主要接口由 SSHClient 提供,其作为客户端用于连接 SSH 服务,每次连接都会生成一个会话 session,在一个 session 中进行具体操作。我们来看一个基本的使用例子:

package net.schmizz.sshj.examples;

import net.schmizz.sshj.SSHClient;
import net.schmizz.sshj.common.IOUtils;
import net.schmizz.sshj.connection.channel.direct.Session;
import net.schmizz.sshj.connection.channel.direct.Session.Command;

import java.io.Console;
import java.io.IOException;
import java.util.concurrent.TimeUnit;

/** 执行远程命令 */
public class Exec {
    private static final Console con = System.console();

    public static void main(String... args)
            throws IOException {
        final SSHClient ssh = new SSHClient();
        ssh.loadKnownHosts();
        ssh.connect("localhost");
        Session session = null;
        try {
            ssh.authPublickey(System.getProperty("user.name"));
            session = ssh.startSession();
            final Command cmd = session.exec("ping -c 1 toutiao.com");
            con.writer().print(IOUtils.readFully(cmd.getInputStream()).toString());
            cmd.join(5, TimeUnit.SECONDS);
            con.writer().print("n** exit status: " + cmd.getExitStatus());
        } finally {
            try {
                if (session != null) {
                    session.close();
                }
            } catch (IOException e) {
                // 处理异常
            }
            
            ssh.disconnect();
        }
    }

}

这是使用 SSHJ 在远程服务器上执行命令的例子。首先创建一个 SSHClient,再加载 know_hosts,并连接到 localhost 所在的 SSH 服务。然后,使用本机用户名对应的公钥进行 SSH 登录验证,并启动会话。成功建立连接后,使用 session 的 exec 接口在 SSH 服务所在远程执行了一条 ping 命令,并从远程读取命令行输出,返回到本地命令行进行打印。最终,在完成任务后,关闭会话并断开连接。以此为基础可以实现远程命令的程序化实现,把需要手动登录 SSH 并执行命令的过程自动化。

SSHJ 实现了 SCP 安全拷贝协议,用于加密的文件在本地和远程之间拷贝复制。在 SSHClient 连接成功之后,使用 SCPFileTransfer 实现文件的上传和下载:

// SCP下载文件
ssh.newSCPFileTransfer().download("test_file", new FileSystemFile("/tmp/"));

// SCP上传文件
ssh.newSCPFileTransfer().upload(new FileSystemFile(src), "/tmp/");

SSHJ 还实现了 SFTP 安全文件传输协议。与 SCP 相比,SFTP 可靠性高,可断点续传,支持更加广泛的远程文件操作。SSHJ 中使用 SFTPClient 来作为 SFTP 的客户端,在 SSHClient 连接成功后,创建 SFTPClient,并使用 put 和 get 进行上传和下载:

// SFTP下载
final SFTPClient sftp = ssh.newSFTPClient();
try {
    sftp.get("test_file", new FileSystemFile("/tmp"));
} finally {
    sftp.close();
}

// SFTP上传
final SFTPClient sftp = ssh.newSFTPClient();
try {
    sftp.put(new FileSystemFile(src), "/tmp");
} finally {
    sftp.close();
}

利用 SSHJ,我们还就可以很方便地实现一个交互式 SSH 客户端,在本地命令行上实现对远程命令行的交互:

package net.schmizz.sshj.examples;

import net.schmizz.sshj.SSHClient;
import net.schmizz.sshj.common.StreamCopier;
import net.schmizz.sshj.connection.channel.direct.Session;
import net.schmizz.sshj.connection.channel.direct.Session.Shell;
import net.schmizz.sshj.transport.verification.ConsoleKnownHostsVerifier;
import net.schmizz.sshj.transport.verification.OpenSSHKnownHosts;

import java.io.File;
import java.io.IOException;
import net.schmizz.sshj.common.LoggerFactory;

/** 交互式SSH客户端 */
class RudimentaryPTY {

    public static void main(String... args)
            throws IOException {

        final SSHClient ssh = new SSHClient();

        final File khFile = new File(OpenSSHKnownHosts.detectSSHDir(), "known_hosts");
        ssh.addHostKeyVerifier(new ConsoleKnownHostsVerifier(khFile, System.console()));

        ssh.connect("localhost");
        try {

            ssh.authPublickey(System.getProperty("user.name"));

            final Session session = ssh.startSession();
            try {

                session.allocateDefaultPTY();

                final Shell shell = session.startShell();

                new StreamCopier(shell.getInputStream(), System.out, LoggerFactory.DEFAULT)
                        .bufSize(shell.getLocalMaxPacketSize())
                        .spawn("stdout");

                new StreamCopier(shell.getErrorStream(), System.err, LoggerFactory.DEFAULT)
                        .bufSize(shell.getLocalMaxPacketSize())
                        .spawn("stderr");

                new StreamCopier(System.in, shell.getOutputStream(), LoggerFactory.DEFAULT)
                        .bufSize(shell.getRemoteMaxPacketSize())
                        .copy();

            } finally {
                session.close();
            }

        } finally {
            ssh.disconnect();
        }
    }

}

在这个例子中,使用了会话的 startShell 来启动一个命令行,而不像我们的第一个例子那样创建会话。在此之后,使用 SSHJ 提供的 StreamCopier,进行远程命令行输出流的获取,以及本地输入流的上传,从而完成了一个实时交互的 SSH 命令行。

SSHJ - 功能齐全的Java SSH库

SSH协议与SSHJ库

总结

SSHJ 作为一个使用 Java 语言实现的 SSH 库,其对于 SSH 协议的实现十分全面,包含的特性众多,在其所提供的 SSH 实现的比较中,SSHJ 对于协议和算法的实现覆盖程度很高,是实现 SSH 协议相关代码逻辑和应用的优秀选择。

SSHJ 项目代码质量高,历经数年的开发,项目一直处于活跃的开发和维护状态;项目代码量不大,代码结构设计较好,且提供了丰富的使用例子,值得有兴趣的开发者进行更进一步的学习研究和开源贡献。

声明:本站部分内容来自互联网,如有版权侵犯或其他问题请与我们联系,我们将立即删除或处理。
▍相关推荐
更多资讯 >>>