com.jcraft.jsch.JSchException:UnknownHostKey

Ale*_*lex 167 java ssh jsch

我正在尝试使用Jsch在Java中建立SSH连接.我的代码产生以下异常:

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
Run Code Online (Sandbox Code Playgroud)

我找不到如何在Jsch文档中验证主机密钥.我在下面提供了我的代码.

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);
        } 
    }
}
Run Code Online (Sandbox Code Playgroud)

Pas*_*ent 211

我要么:

  1. 尝试ssh从命令行接受公钥(主机将被添加到~/.ssh/known_hosts,然后一切都应该从Jsch正常工作)- 或 -
  2. 使用以下代码将JSch配置为不使用"StrictHostKeyChecking"(这会引入不安全因素并且只应用于测试目的):

    java.util.Properties config = new java.util.Properties(); 
    config.put("StrictHostKeyChecking", "no");
    session.setConfig(config);
    
    Run Code Online (Sandbox Code Playgroud)

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

  • `JSch #setConfig("StrictHostKeyChecking","no")`将完成相同的工作,但只需一行 (35认同)
  • 这是不安全的,实际上不应该被选为该原则的正确答案.setKnownHosts()和setFingerPrint()选项是在不忽略ssh进程的一个重要方面的情况下执行此操作的方法.编辑:根据我的经验,#1在Eclipse等某些IDE环境中不起作用. (17认同)
  • 旁注:我用这个反馈来配置我的`〜/ .ssh/config`文件来解决上面的错误,当时我无法修改源代码 (2认同)

ksz*_*tan 36

虽然这个问题已经得到了回答,但我发现自己有一种情况甚至现有的known_hosts条目都无济于事.当SSH服务器发送ECDSA指纹时会发生这种情况,因此,您将拥有如下条目:

|1|+HASH=|HASH= ecdsa-sha2-nistp256 FINGERPRINT=
Run Code Online (Sandbox Code Playgroud)

问题是JSch 更喜欢 SHA_RSA,并且在连接时会尝试比较SHA-RSA指纹,这将导致"未知主机"错误.

要解决此问题,只需运行:

$ ssh-keyscan -H -t rsa example.org >> known_hosts
Run Code Online (Sandbox Code Playgroud)

或者向Jcraft抱怨喜欢使用SHA_RSA而不是使用本地HostKeyAlgorithms设置,尽管他们似乎并不太急于修复他们的错误.

  • 我们遇到了类似的情况,使用“ecdsa-sha2-nistp384”,并且您的解决方案工作得很好。根据 [openssh-keyscan 手册](https://man.openbsd.org/ssh-keyscan) 和我们的需要,我们运行 `ssh-keyscan -t rsa,ecdsa example.org >>known_hosts`。 (2认同)
  • 我有这样的问题,但例外是 *JSchException: reject HostKey:* 而不是 *JSchException: UnknownHostKey* (这可能会帮助其他一些用户) (2认同)

kri*_*arp 33

避免主机密钥检查是一种安全风险.

JSch使用HostKeyRepository接口及其默认实现KnownHosts类来管理它.您可以通过实现HostKeyRepository来提供允许特定键的备用实现.或者,您可以将您要允许的密钥保存在known_hosts格式的文件中并调用

jsch.setKnownHosts(knownHostsFileName);
Run Code Online (Sandbox Code Playgroud)

或者使用公钥String,如下所示.

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

有关详细信息,请参阅Javadoc.

这将是一个更安全的解决方案.

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


Cha*_*ski 16

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

jsch.setKnownHosts("C:\\Users\\cabbott\\known_hosts");
Run Code Online (Sandbox Code Playgroud)

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

也许其他人可以建议另一种Windows替代品.我发现putty处理SSH密钥的方式是将它们以非标准格式存储在注册表中,这很麻烦.


小智 10

提供主机的公共rsa密钥: -

String knownHostPublicKey = "mywebsite.com ssh-rsa AAAAB3NzaC1.....XL4Jpmp/";

session.setKnownHosts(new ByteArrayInputStream(knownHostPublicKey.getBytes()));
Run Code Online (Sandbox Code Playgroud)


Vis*_*mel 6

您还可以执行以下代码.它经过测试和运行.

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;
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

请替换适当的值.


Ama*_*y D 6

你也可以简单地做

session.setConfig("StrictHostKeyChecking", "no");
Run Code Online (Sandbox Code Playgroud)

它不安全,并且是不适合实时环境的解决方法,因为它将禁用全局已知的主机密钥检查。

  • 尽管此代码可以帮助回答问题,但仅代码的答案质量不高。更好的答案是解释代码的作用,告诉代码在哪里插入,解释为什么采用这种方法以及链接到相关文档。 (2认同)