我正在开发一个 Java 应用程序,必须将数据存储在 SFTP 中。
测试环境有密码认证,同时生产环境有授权的OPENSSH密钥(标准
id_rsa
)用作IdentityFile
。这意味着我必须将两种身份验证方法保留在同一代码中。
我就是这么处理的。基本上,如果未设置
identityFile
路径,它将利用密码登录。请注意,所有变量都来自 application.properties
:
JSch jsch = new JSch();
jsch.setKnownHosts(knownHosts);
if (!identityFile.equals("")) {
jsch.addIdentity(identityFile, passphrase);
}
Session jschSession = jsch.getSession(user, host, port);
jschSession.setConfig("StrictHostKeyChecking", "no");
if (identityFile.equals("")) {
jschSession.setPassword(pass);
jschSession.setConfig("PreferredAuthentications", "password");
} else {
jschSession.setConfig("PreferredAuthentications", "publickey");
}
jschSession.connect();
ChannelSftp channelSftp = (ChannelSftp) jschSession.openChannel("sftp");
channelSftp.connect();
我可以连接到测试环境,但无法连接到生产 SFTP,因此我使用(希望)相同的配置在开发服务器上实例化了 SFTP。我遵循了this指南。
通过 shell 和 FileZilla 连接到开发 SFTP,指定
IdentityFile
,工作正常。通过 Java、shell 和 FileZilla 使用密码连接到测试 SFTP,工作正常。
Java 无法使用
IdentityFile
连接。如果我使用 RSA 私钥,我得到的只是 com.jcraft.jsch.SftpException: Auth fail
上的 jschSession.connect()
。
生产环境使用OPENSSH私钥,所以无法转换。如果我使用 OPENSSH 密钥,则会在
invalid privatekey: [B@48c76607
上收到 jsch.addIdentity(identityFile)
错误。正如我在here读到的那样,JSch
不喜欢 OPENSSH 密钥。
这意味着 JSch 需要 RSA 密钥,但它也无法连接。我稍后会考虑将 OPENSSH 转换为 RSA。
我尝试在 Windows 和 Ubuntu dockerized VM 上运行
jar
。 id_rsa
文件在两个系统上都具有正确的权限。
我使用的
JSch
版本是jsch-0.1.55.jar
。我正在跑步Java 8
。
这些是使用 RSA 密钥连接后的 JSch 日志。
Connecting to <HOST> port <PORT>
Connection established
Remote version string: SSH-2.0-OpenSSH_8.9p1 Ubuntu-3ubuntu0.3
Local version string: SSH-2.0-JSCH-0.1.54
CheckCiphers: aes256-ctr,aes192-ctr,aes128-ctr,aes256-cbc,aes192-cbc,aes128-cbc,3des-ctr,arcfour,arcfour128,arcfour256
CheckKexes: diffie-hellman-group14-sha1,ecdh-sha2-nistp256,ecdh-sha2-nistp384,ecdh-sha2-nistp521
CheckSignatures: ecdsa-sha2-nistp256,ecdsa-sha2-nistp384,ecdsa-sha2-nistp521
SSH_MSG_KEXINIT sent
SSH_MSG_KEXINIT received
kex: server: curve25519-sha256,[email protected],ecdh-sha2-nistp256,ecdh-sha2-nistp384,ecdh-sha2-nistp521,[email protected],diffie-hellman-group-exchange-sha256,diffie-hellman-group16-sha512,diffie-hellman-group18-sha512,diffie-hellman-group14-sha256
kex: server: rsa-sha2-512,rsa-sha2-256,ecdsa-sha2-nistp256,ssh-ed25519
kex: server: [email protected],aes128-ctr,aes192-ctr,aes256-ctr,[email protected],[email protected]
kex: server: [email protected],aes128-ctr,aes192-ctr,aes256-ctr,[email protected],[email protected]
kex: server: [email protected],[email protected],[email protected],[email protected],[email protected],[email protected],[email protected],hmac-sha2-256,hmac-sha2-512,hmac-sha1
kex: server: [email protected],[email protected],[email protected],[email protected],[email protected],[email protected],[email protected],hmac-sha2-256,hmac-sha2-512,hmac-sha1
kex: server: none,[email protected]
kex: server: none,[email protected]
kex: server:
kex: server:
kex: client: ecdh-sha2-nistp256,ecdh-sha2-nistp384,ecdh-sha2-nistp521,diffie-hellman-group14-sha1,diffie-hellman-group-exchange-sha256,diffie-hellman-group-exchange-sha1,diffie-hellman-group1-sha1
kex: client: ssh-rsa,ssh-dss,ecdsa-sha2-nistp256,ecdsa-sha2-nistp384,ecdsa-sha2-nistp521
kex: client: aes128-ctr,aes128-cbc,3des-ctr,3des-cbc,blowfish-cbc,aes192-ctr,aes192-cbc,aes256-ctr,aes256-cbc
kex: client: aes128-ctr,aes128-cbc,3des-ctr,3des-cbc,blowfish-cbc,aes192-ctr,aes192-cbc,aes256-ctr,aes256-cbc
kex: client: hmac-md5,hmac-sha1,hmac-sha2-256,hmac-sha1-96,hmac-md5-96
kex: client: hmac-md5,hmac-sha1,hmac-sha2-256,hmac-sha1-96,hmac-md5-96
kex: client: none
kex: client: none
kex: client:
kex: client:
kex: server->client aes128-ctr hmac-sha1 none
kex: client->server aes128-ctr hmac-sha1 none
SSH_MSG_KEX_ECDH_INIT sent
expecting SSH_MSG_KEX_ECDH_REPLY
Host '<HOST>' is known and matches the ECDSA host key
SSH_MSG_NEWKEYS sent
SSH_MSG_NEWKEYS received
SSH_MSG_SERVICE_REQUEST sent
SSH_MSG_SERVICE_ACCEPT received
Authentications that can continue: publickey
Next authentication method: publickey
Disconnecting from <HOST> port <PORT>
实际上,我的 SSH/SFTP 配置中缺少某些内容,因为我的应用程序也无法连接到同一服务器上的 SSH。
非常感谢任何帮助!
感谢@MartinPrikryl 和this链接的线程,我找到了解决方案。看起来有人分叉了原来的
jsch
库并解决了此类问题。交换 Maven 依赖项
<dependency>
<groupId>com.jcraft</groupId>
<artifactId>jsch</artifactId>
<version>0.1.55</version>
</dependency>
到
<dependency>
<groupId>com.github.mwiede</groupId>
<artifactId>jsch</artifactId>
<version>0.2.13</version>
</dependency>
足以解决它。完全不需要重构代码。
这个库是一个第三方的、独立于原始库的分支
jsch
。这意味着它可能仍然存在一些缺陷,他们可以随时停止支持它(就像com.jcraft
)。就我个人而言,我更喜欢实际修复,但解决它太紧迫了。另外,这个叉子允许我使用 OPENSSH
键。使用转换后的 RSA 密钥可能会出现问题,因为我会避免接触任何生产环境配置。