com.jcraft.jsch.JSchException:UnknownHostKey

我试图用Jschbuild立一个Java连接的SSH连接。 我的代码产生以下exception:

com.jcraft.jsch.JSchException: UnknownHostKey: mywebsite.com. RSA key fingerprint is 22:fb:ee:fe:18:cd:aa:9a:9c:78:89:9f:b4:78:75:b4 

我无法find如何validationJsch文档中的主机密钥。 我在下面列出了我的代码。

 import com.jcraft.jsch.JSch; import com.jcraft.jsch.Session; public class ssh { public static void main(String[] arg) { try { JSch jsch = new JSch(); //create SSH connection String host = "mywebsite.com"; String user = "username"; String password = "123456"; Session session = jsch.getSession(user, host, 22); session.setPassword(password); session.connect(); } catch(Exception e) { System.out.println(e); } } } 

我会:

  1. 尝试从命令行ssh接受公共密钥(主机将被添加到~/.ssh/known_hosts ,一切应该从Jsch罚款) – 或 –
  2. configurationJSch不使用“StrictHostKeyChecking”(这引入了不安全感,应该仅用于testing目的),使用以下代码:

     java.util.Properties config = new java.util.Properties(); config.put("StrictHostKeyChecking", "no"); session.setConfig(config); 

选项#1(将主机添加到~/.ssh/known_hosts文件)具有我的偏好。

避免主机密钥检查是安全风险。

JSch使用HostKeyRepository接口及其默认实现KnownHosts类来pipe理这个。 您可以通过实现HostKeyRepository来提供一个允许特定键的替代实现。 或者你可以保留你想要在文件中以known_hosts格式允许的密钥并进行调用

 jsch.setKnownHosts(knownHostsFileName); 

或者使用公钥string如下。

 String knownHostPublicKey = "mysite.com ecdsa-sha2-nistp256 AAAAE............/3vplY"; jsch.setKnownHosts(new ByteArrayInputStream(knownHostPublicKey.getBytes())); 

请参阅Javadoc了解更多详情。

这将是一个更安全的解决scheme。

Jsch是开源的,你可以从这里下载源代码。 在示例文件夹中,查找KnownHosts.java以了解更多详细信息。

根据您使用ssh的程序,获得正确密钥的方式可能会有所不同。 腻子(Windows常用)使用他们自己的ssh密钥格式。 对于我所见过的大多数Linux和BSD变种,您只需要查看~/.ssh/known_hosts 。 我通常从Linux机器ssh,然后将该文件复制到Windows机器。 然后我使用类似的东西

 jsch.setKnownHosts("C:\\Users\\cabbott\\known_hosts"); 

假设我已将该文件放置在Windows机器上的C:\Users\cabbott 。 如果您无法访问Linux机器,请尝试http://www.cygwin.com/

也许别人可以build议另一个Windows的select。 我发现putty处理SSH密钥的方法是将它们以非标准格式存储在registry中,麻烦提取。

提供主机的公共rsa密钥:

 String knownHostPublicKey = "mywebsite.com ssh-rsa AAAAB3NzaC1.....XL4Jpmp/"; session.setKnownHosts(new ByteArrayInputStream(knownHostPublicKey.getBytes())); 

您也可以执行下面的代码。 它被testing和工作。

 import com.jcraft.jsch.Channel; import com.jcraft.jsch.JSch; import com.jcraft.jsch.JSchException; import com.jcraft.jsch.Session; import com.jcraft.jsch.UIKeyboardInteractive; import com.jcraft.jsch.UserInfo; public class SFTPTest { public static void main(String[] args) { JSch jsch = new JSch(); Session session = null; try { session = jsch.getSession("username", "mywebsite.com", 22); //default port is 22 UserInfo ui = new MyUserInfo(); session.setUserInfo(ui); session.setPassword("123456".getBytes()); session.connect(); Channel channel = session.openChannel("sftp"); channel.connect(); System.out.println("Connected"); } catch (JSchException e) { e.printStackTrace(System.out); } catch (Exception e){ e.printStackTrace(System.out); } finally{ session.disconnect(); System.out.println("Disconnected"); } } public static class MyUserInfo implements UserInfo, UIKeyboardInteractive { @Override public String getPassphrase() { return null; } @Override public String getPassword() { return null; } @Override public boolean promptPassphrase(String arg0) { return false; } @Override public boolean promptPassword(String arg0) { return false; } @Override public boolean promptYesNo(String arg0) { return false; } @Override public void showMessage(String arg0) { } @Override public String[] promptKeyboardInteractive(String arg0, String arg1, String arg2, String[] arg3, boolean[] arg4) { return null; } } } 

请replace适当的值。

你也可以简单的做

 session.setConfig("StrictHostKeyChecking", "no"); 

这是不安全的,这是一个变通办法,不适合现场环境,因为它会禁用全局已知的主机密钥检查。

虽然这个问题已经得到了普遍的回答,但是我发现自己有一种情况 ,即使现有的known_hosts条目没有帮助。 当SSH服务器发送ECDSA指纹时会发生这种情况,因此会出现如下所示的条目:

 |1|+HASH=|HASH= ecdsa-sha2-nistp256 FINGERPRINT= 

问题是JSch 更喜欢 SHA_RSA,而连接它时会尝试比较SHA-RSA指纹,这会导致关于“未知主机”的错误。

要解决这个简单的运行:

 $ ssh-keyscan -H -t rsa example.org >> known_hosts 

或者向Jcraft抱怨关于使用SHA_RSA而不是使用本地的HostKeyAlgorithms设置,尽pipe他们似乎不太愿意修复它们的错误 。

只需要replace“用户”,“通过”,“SSHD_IP”。 然后用服务器的〜/ .ssh / known_hosts的内容创build一个名为known_hosts.txt的文件。 你会得到一个壳。

 public class Known_Hosts { public static void main(String[] arg) { try { JSch jsch = new JSch(); jsch.setKnownHosts("known_hosts.txt"); Session session = jsch.getSession("user", "SSHD_IP", 22); session.setPassword("pass"); session.connect(); Channel channel = session.openChannel("shell"); channel.setInputStream(System.in); channel.setOutputStream(System.out); channel.connect(); } catch (Exception e) { System.out.println(e); } } } 

将该主机添加到〜/ .ssh / known_hosts。

有没有人能够解决这个问题? 我正在使用Jscp scp文件使用公钥authentication(我不想使用密码authentication)。 帮助将不胜感激!

这个stackoverflow条目是关于主机密钥检查,并且与公钥authentication没有关系。

至于公钥authentication,请使用普通(非encryption)私钥尝试下面的示例 ,

设置已知主机比设置打印值更好。

当您设置已知的主机时,尝试从应用程序运行的框中手动ssh(第一次,在应用程序运行之前)。

 JSch jsch = new JSch(); Session session = null; try { session = jsch.getSession("user", "hostname", 22); // default UserInfo ui = new MyUserInfo(); session.setUserInfo(ui); session.setPassword("password".getBytes()); java.util.Properties config = new java.util.Properties(); config.put("StrictHostKeyChecking", "no"); session.setConfig(config); session.connect(); Channel channel = session.openChannel("sftp"); channel.connect(); System.out.println("Connected"); } catch (JSchException e) { e.printStackTrace(System.out); } catch (Exception e) { e.printStackTrace(System.out); } finally { session.disconnect(); System.out.println("Disconnected"); } } 

我在这个愚蠢的问题上浪费了很多时间,而且我认为这个消息是非常正确的“在我正在访问的文件中没有主机”,但是你的系统上可以有不止一个know_host文件(比如我使用mobaXterm,它保持在自己的根目录安装目录的安装目录内)。

如果您遇到:它正在从命令行运行,但不能形成应用程序尝试使用ssh访问远程服务器,并使用verbose -v选项检查当前使用哪个文件的示例如下:

  ssh -v git@gitlab.com OpenSSH_6.2p2, OpenSSL 1.0.1g 7 Apr 2014 debug1: Reading configuration data /etc/ssh_config debug1: Connecting to gitlab.com [104.210.2.228] port 22. debug1: Connection established. debug1: identity file /home/mobaxterm/.ssh/id_rsa type 1 debug1: identity file /home/mobaxterm/.ssh/id_rsa-cert type -1 debug1: identity file /home/mobaxterm/.ssh/id_dsa type -1 debug1: identity file /home/mobaxterm/.ssh/id_dsa-cert type -1 debug1: identity file /home/mobaxterm/.ssh/id_ecdsa type -1 debug1: identity file /home/mobaxterm/.ssh/id_ecdsa-cert type -1 debug1: Enabling compatibility mode for protocol 2.0 debug1: Local version string SSH-2.0-OpenSSH_6.2 debug1: Remote protocol version 2.0, remote software version OpenSSH_7.2p2 Ubuntu-4ubuntu2.1 debug1: match: OpenSSH_7.2p2 Ubuntu-4ubuntu2.1 pat OpenSSH* debug1: SSH2_MSG_KEXINIT sent debug1: SSH2_MSG_KEXINIT received debug1: kex: server->client aes128-ctr hmac-sha1-etm@openssh.com zlib@openssh.com debug1: kex: client->server aes128-ctr hmac-sha1-etm@openssh.com zlib@openssh.com debug1: sending SSH2_MSG_KEX_ECDH_INIT debug1: expecting SSH2_MSG_KEX_ECDH_REPLY debug1: Server host key: RSA b6:03:0e:39:97:9e:d0:e7:24:ce:a3:77:3e:01:42:09 debug1: Host 'gitlab.com' is known and matches the RSA host key. debug1: Found key in /home/mobaxterm/.ssh/known_hosts:19 debug1: ssh_rsa_verify: signature correct 

正如你所看到的钥匙被发现在:

 debug1: Found key in /home/mobaxterm/.ssh/known_hosts:19 

而不是在我的Windows家庭在C:\ Users \ my_local_user \ .ssh,我只是合并他们和alignment解决问题。

希望这将有助于未来的人