使用JSch实现Java SSH客户端公钥认证失败求助
JSch公钥认证失败修复方案
问题背景
用Java开发SSH客户端执行远程命令,用户名/密码认证正常,但公钥认证抛出错误:
com.jcraft.jsch.JSchException: Auth fail at com.jcraft.jsch.Session.connect(Session.java:519)
本地shell的ssh命令用同一密钥能正常认证,说明密钥本身无问题,使用的JSch版本为0.1.55。
原代码
String remoteShellScript = "vtmenu"; Session jschSession = null; try { JSch jsch = new JSch(); jschSession = jsch.getSession(USERNAME, REMOTE_HOST, REMOTE_PORT); jsch.addIdentity("/home/ZZZZZZ/.ssh/id_rsa"); jschSession.setConfig("PreferredAuthentications", "publickey"); jschSession.setConfig("StrictHostKeyChecking", "no"); jschSession.connect(SESSION_TIMEOUT);
关键日志分析
从调试日志可以看到:
- 服务器是OpenSSH 7.4,返回
server-sig-algs=<rsa-sha2-256,rsa-sha2-512>,优先要求RSA-SHA2签名算法 - JSch 0.1.55对RSA-SHA2签名的支持存在缺陷,导致出现
rsa-sha2-512 preauth failure、rsa-sha2-256 preauth failure的错误
修复方案
1. 升级JSch版本(推荐)
将JSch依赖升级到0.1.56及以上,新版本修复了RSA-SHA2签名的兼容性问题,适配OpenSSH 7.4及以上版本的签名要求。
2. 强制使用ssh-rsa算法(临时方案)
如果暂时无法升级版本,可在Session配置中强制添加ssh-rsa到支持的公钥算法列表,服务器通常会兼容该算法:
jschSession.setConfig("PubkeyAcceptedAlgorithms", "+ssh-rsa");
3. 检查私钥文件权限
确保本地私钥文件/home/ZZZZZZ/.ssh/id_rsa的权限为600,JSch对私钥权限敏感,权限过宽会拒绝使用:
chmod 600 /home/ZZZZZZ/.ssh/id_rsa
4. 显式指定私钥密码(如果有)
如果私钥设置了密码,需要在添加身份时显式传入密码,避免因密码缺失导致认证失败:
jsch.addIdentity("/home/ZZZZZZ/.ssh/id_rsa", "你的私钥密码");
修改后的示例代码
String remoteShellScript = "vtmenu"; Session jschSession = null; try { JSch jsch = new JSch(); // 若私钥有密码,添加第二个参数传入密码 jsch.addIdentity("/home/ZZZZZZ/.ssh/id_rsa"); jschSession = jsch.getSession(USERNAME, REMOTE_HOST, REMOTE_PORT); // 临时方案:强制兼容ssh-rsa算法 jschSession.setConfig("PubkeyAcceptedAlgorithms", "+ssh-rsa"); jschSession.setConfig("PreferredAuthentications", "publickey"); jschSession.setConfig("StrictHostKeyChecking", "no"); jschSession.connect(SESSION_TIMEOUT); // 后续执行远程命令逻辑... } catch (JSchException e) { e.printStackTrace(); } finally { // 确保会话关闭 if (jschSession != null && jschSession.isConnected()) { jschSession.disconnect(); } }
内容的提问来源于stack exchange,提问作者Andrea
相关产品推荐
相关产品推荐

