You need to enable JavaScript to run this app.
最新活动
大模型
产品
解决方案
定价
生态与合作
支持与服务
开发者
了解我们

Apache MINA SSHD 2.11.0中如何从字节数组加载私钥用于SFTP认证?

Apache MINA SSHD 2.11.0中如何从字节数组加载私钥用于SFTP认证?

我之前刚好做过从JSch迁移到Apache MINA SSHD的工作,完全理解你不想把内存里的私钥写到临时文件的需求——毕竟这样既不安全也没必要。下面就给你详细讲下怎么直接从字节数组加载私钥完成认证,一步到位解决你的两个问题。

核心思路:用内存资源包装私钥字节数组

MINA SSHD提供了ByteArrayResource类,可以把字节数组直接包装成它能识别的资源对象,再配合密钥解析器就能直接加载私钥对,全程不需要碰磁盘。

完整代码示例

下面是对应你JSch代码的MINA SSHD实现,支持带密码和不带密码的私钥:

import org.apache.sshd.client.SshClient;
import org.apache.sshd.client.session.ClientSession;
import org.apache.sshd.common.config.keys.loader.openssh.OpenSSHKeyPairResourceParser;
import org.apache.sshd.common.session.SessionContext;
import org.apache.sshd.common.util.io.resource.ByteArrayResource;
import org.apache.sshd.sftp.client.SftpClient;

import java.io.IOException;
import java.security.KeyPair;

public class SftpByteKeyAuth {
    public static void main(String[] args) throws IOException {
        // 替换成你的实际参数
        String username = "your-username";
        String host = "your-host";
        int port = 22;
        byte[] privateKeyBytes = /* 你的私钥字节数组 */;
        char[] passphrase = "your-passphrase".toCharArray(); // 无密码的话设为null

        // 初始化SSH客户端
        try (SshClient sshClient = SshClient.setUpDefaultClient()) {
            // 对应JSch里的StrictHostKeyChecking=no,生产环境建议替换为实际的主机密钥验证逻辑
            sshClient.setHostKeyVerifier((session, hostKeyHost, key) -> true);
            sshClient.start();

            // 建立会话
            try (ClientSession session = sshClient.connect(username, host, port)
                    .verify()
                    .getSession()) {

                // 加载私钥对
                KeyPair keyPair;
                ByteArrayResource keyResource = new ByteArrayResource("sftp-key", privateKeyBytes);
                if (passphrase != null) {
                    // 加载带密码的私钥
                    keyPair = OpenSSHKeyPairResourceParser.INSTANCE.loadKeyPair(
                            SessionContext.EMPTY, keyResource, passphrase);
                } else {
                    // 加载无密码的私钥
                    keyPair = OpenSSHKeyPairResourceParser.INSTANCE.loadKeyPair(
                            SessionContext.EMPTY, keyResource, null);
                }

                // 添加私钥身份并完成认证
                session.addPublicKeyIdentity(keyPair);
                session.auth().verify();

                // 打开SFTP通道并操作
                try (SftpClient sftpClient = session.createSftpClient()) {
                    // 示例:列出根目录文件
                    sftpClient.ls("/").forEach(System.out::println);
                }
            } finally {
                sshClient.stop();
            }
        }
    }
}

关键细节说明

  • 私钥格式兼容:上面用的OpenSSHKeyPairResourceParser是处理OpenSSH格式私钥(比如id_rsa那种)的解析器,如果你的私钥是PKCS#8格式,可以换成PKCS8KeyPairResourceParser,用法完全一致。
  • 跳过主机密钥验证:代码里的setHostKeyVerifier对应JSch的StrictHostKeyChecking=no,生产环境强烈建议不要这么做,最好配置可信的主机密钥列表,避免中间人攻击。
  • 资源自动释放:用了try-with-resources语法,确保SSH客户端、会话、SFTP客户端都能自动关闭,避免资源泄漏。

针对你的问题的直接回答

  1. 如何从字节数组加载私钥:通过ByteArrayResource包装字节数组,再用对应的密钥解析器(如OpenSSHKeyPairResourceParser)加载成KeyPair对象,最后添加到会话的身份列表中完成认证。
  2. 是否需要临时文件:完全不需要!上面的代码全程在内存中处理私钥,没有任何磁盘写入操作,既安全又高效。

备注:内容来源于stack exchange,提问作者Tom

火山引擎 最新活动