我正在尝试使用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
我找不到如何在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);
}
}
}
答案 0 :(得分:202)
我要么:
ssh
并接受公钥(主机将添加到~/.ssh/known_hosts
,然后一切都可以从Jsch正常工作) -OR - 使用以下代码将JSch配置为不使用“StrictHostKeyChecking”(这会引入不安全因素并且只应用于测试目的):
java.util.Properties config = new java.util.Properties();
config.put("StrictHostKeyChecking", "no");
session.setConfig(config);
选项#1(将主机添加到~/.ssh/known_hosts
文件)有我的偏好。
答案 1 :(得分:32)
避免主机密钥检查存在安全风险。
JSch使用HostKeyRepository接口及其默认实现KnownHosts类来管理它。您可以通过实现HostKeyRepository来提供允许特定键的备用实现。或者,您可以在known_hosts format中的文件中保留要允许的密钥并调用
jsch.setKnownHosts(knownHostsFileName);
或使用如下公钥String。
String knownHostPublicKey = "mysite.com ecdsa-sha2-nistp256 AAAAE............/3vplY";
jsch.setKnownHosts(new ByteArrayInputStream(knownHostPublicKey.getBytes()));
有关详细信息,请参阅Javadoc。
这将是一个更安全的解决方案。
Jsch是开源的,您可以从here下载源代码。在示例文件夹中,查找KnownHosts.java以了解更多详细信息。
答案 2 :(得分:28)
虽然这个问题已经得到了回答,但我发现自己即使现有的 known_hosts 条目无效也会有case。当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 设置,尽管他们似乎不太eager来修复他们的bugs }。
答案 3 :(得分:16)
根据您用于ssh的程序,获取正确密钥的方式可能会有所不同。 Putty(受Windows欢迎)使用自己的格式来生成ssh密钥。对于我见过的大多数Linux和BSD变种,您只需要查看~/.ssh/known_hosts
。我通常从Linux机器ssh,然后将此文件复制到Windows机器。然后我使用类似于
jsch.setKnownHosts("C:\\Users\\cabbott\\known_hosts");
假设我已将文件放在C:\Users\cabbott
的Windows机器上。如果您无法访问Linux计算机,请尝试http://www.cygwin.com/
也许其他人可以推荐另一种Windows替代品。我发现putty处理SSH密钥的方式是将它们以非标准格式存储在注册表中,这很麻烦。
答案 4 :(得分:10)
提供主机的公共rsa密钥: -
String knownHostPublicKey = "mywebsite.com ssh-rsa AAAAB3NzaC1.....XL4Jpmp/";
session.setKnownHosts(new ByteArrayInputStream(knownHostPublicKey.getBytes()));
答案 5 :(得分: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;
}
}
}
请替换相应的值。
答案 6 :(得分:5)
你也可以简单地做
session.setConfig("StrictHostKeyChecking", "no");
它不安全,而且它不适用于实时环境,因为它会禁用全局已知的主机密钥检查。
答案 7 :(得分:1)
只需替换“user”,“pass”,“SSHD_IP”即可。并使用服务器的〜/ .ssh / known_hosts内容创建一个名为known_hosts.txt的文件。你会得到一个shell。
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);
}
}
}
答案 8 :(得分:1)
我在这个愚蠢的问题上浪费了很多时间,而且我认为这个消息是非常正确的#34;文件中没有主机我正在访问"但是你可以在你的系统上拥有多个know_host文件(例如我使用mobaXterm并且它将自己保留在安装目录中,从该根目录安装home)。
如果您遇到:它从命令行工作但不构成应用程序尝试使用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下,我只是将它们合并并对齐以解决问题。
希望这有助于将来的某人
答案 9 :(得分:0)
有没有人能够解决这个问题?我使用Jscp使用公钥scp文件 身份验证(我不想使用密码身份验证)。帮助将不胜感激!!!
此stackoverflow条目与主机密钥检查有关,与公钥认证无关。
对于公钥认证,请使用普通(非加密)私钥尝试following sample,
答案 10 :(得分:0)
设置已知主机优于设置fingure打印值。
设置已知主机时,请尝试从应用程序运行的框中手动ssh(第一次,在应用程序运行之前)。
答案 11 :(得分:0)
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");
}
}