使用JSch连接到远程服务器时获取UnknownHostKey

时间:2015-07-31 14:09:34

标签: java ssh jsch

我试图通过JSch连接到Java远程服务器,但我收到了错误。

我有这段代码:

public static void myCode() {
    String command = "ls /home";
    String userName = "username";
    String password = "pass";
    String connectionIP = "XXX.XXX.XXX.XXX";
    int port = 0000; // example value
    SSHManager instance = new SSHManager(userName, password, connectionIP, "", port);
    String errorMessage = instance.connect();

    if (errorMessage != null) {
        System.out.println(errorMessage);
    }

    String result = instance.sendCommand(command);
    instance.close();
}

SSHManager类:

/* 
 * SSHManager
 * 
 * @author cabbott
 * @version 1.0
 */

import com.jcraft.jsch.*;
import java.io.IOException;
import java.io.InputStream;
import java.util.logging.Level;
import java.util.logging.Logger;

public class SSHManager {

    private static final Logger LOGGER
            = Logger.getLogger(SSHManager.class.getName());
    private JSch jschSSHChannel;
    private String strUserName;
    private String strConnectionIP;
    private int intConnectionPort;
    private String strPassword;
    private Session sesConnection;
    private int intTimeOut;

    private void doCommonConstructorActions(String userName,
            String password, String connectionIP, String knownHostsFileName) {
        jschSSHChannel = new JSch();

        try {
            jschSSHChannel.setKnownHosts(knownHostsFileName);
        } catch (JSchException jschX) {
            logError(jschX.getMessage());
        }

        strUserName = userName;
        strPassword = password;
        strConnectionIP = connectionIP;
    }

    public SSHManager(String userName, String password,
            String connectionIP, String knownHostsFileName) {
        doCommonConstructorActions(userName, password,
                connectionIP, knownHostsFileName);
        intConnectionPort = 22;
        intTimeOut = 60000;
    }

    public SSHManager(String userName, String password, String connectionIP,
            String knownHostsFileName, int connectionPort) {
        doCommonConstructorActions(userName, password, connectionIP,
                knownHostsFileName);
        intConnectionPort = connectionPort;
        intTimeOut = 60000;
    }

    public SSHManager(String userName, String password, String connectionIP,
            String knownHostsFileName, int connectionPort, int timeOutMilliseconds) {
        doCommonConstructorActions(userName, password, connectionIP,
                knownHostsFileName);
        intConnectionPort = connectionPort;
        intTimeOut = timeOutMilliseconds;
    }

    public String connect() {
        String errorMessage = null;

        try {
            sesConnection = jschSSHChannel.getSession(strUserName,
                    strConnectionIP, intConnectionPort);
            sesConnection.setPassword(strPassword);
        // UNCOMMENT THIS FOR TESTING PURPOSES, BUT DO NOT USE IN PRODUCTION
            // sesConnection.setConfig("StrictHostKeyChecking", "no");
            sesConnection.connect(intTimeOut);
        } catch (JSchException jschX) {
            errorMessage = jschX.getMessage();
        }

        return errorMessage;
    }

    private String logError(String errorMessage) {
        if (errorMessage != null) {
            LOGGER.log(Level.SEVERE, "{0}:{1} - {2}",
                    new Object[]{strConnectionIP, intConnectionPort, errorMessage});
        }

        return errorMessage;
    }

    private String logWarning(String warnMessage) {
        if (warnMessage != null) {
            LOGGER.log(Level.WARNING, "{0}:{1} - {2}",
                    new Object[]{strConnectionIP, intConnectionPort, warnMessage});
        }

        return warnMessage;
    }

    public String sendCommand(String command) {
        StringBuilder outputBuffer = new StringBuilder();

        try {
            Channel channel = sesConnection.openChannel("exec");
            ((ChannelExec) channel).setCommand(command);
            InputStream commandOutput = channel.getInputStream();
            channel.connect();
            int readByte = commandOutput.read();

            while (readByte != 0xffffffff) {
                outputBuffer.append((char) readByte);
                readByte = commandOutput.read();
            }

            channel.disconnect();
        } catch (IOException ioX) {
            logWarning(ioX.getMessage());
            return null;
        } catch (JSchException jschX) {
            logWarning(jschX.getMessage());
            return null;
        }

        return outputBuffer.toString();
    }

    public void close() {
        sesConnection.disconnect();
    }

}

当我运行它时,我收到此错误:

  

2015年7月31日下午2:56:44 javaapplication2.SSHManager logError
  SEVERE:null:0 - java.io.FileNotFoundException
  UnknownHostKey:XXX.XXX.XXX.XXX。 RSA密钥指纹是xx:xx:xx:xx:xx:xx:xx:xx:xx:xx:xx:xx:xx:xx:xx
  2015年7月31日下午2:56:45 javaapplication2.SSHManager logWarning
  警告:XXX.XXX.XXX.XXX:0.000 - 会话已关闭

我找到了这个答案:
https://stackoverflow.com/a/2003460/2699664

阅读后我决定删除~/.ssh/known_hosts,然后通过终端中的ssh登录服务器。它告诉我已知主机文件已更新,但此代码出现相同的错误。

我觉得奇怪的另一件事是,当我插入 0000 时,错误的最后一行表示我插入了端口 0.000

有谁知道错误在哪里?

1 个答案:

答案 0 :(得分:1)

默认情况下,JSch应该能够解析您使用known_hosts设置的OpenSSH ssh文件中的已知主机密钥。

但是当您使用路径明确调用JSch.setKnownHosts时(因此FileNotFoundException),您就会将其分解(因此UnknownHostKey)。