You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

JSch认证失败引发SocketTimeoutException问题排查求助

SSH认证失败时Socket客户端超时且无错误返回的问题

我有一个Socket服务,负责监听Java客户端的请求。当请求到达后,服务会通过JSch建立SSH连接到目标服务器获取信息。用户名密码正确时一切正常,但密码错误时,执行session.connect()会触发com.jcraft.jsch.JSchException: Auth fail异常,同时导致客户端与Socket服务的连接抛出SocketTimeoutException: java.net.SocketTimeoutException: Read timed out。异常发生后,代码中的out.println语句无输出,客户端无法收到错误信息。

异常信息

客户端Socket超时异常

SocketTimeoutException:
java.net.SocketTimeoutException: Read timed out
at java.base/java.net.SocketInputStream.socketRead0(Native Method)
at java.base/java.net.SocketInputStream.socketRead(SocketInputStream.java:115)
at java.base/java.net.SocketInputStream.read(SocketInputStream.java:168)
at java.base/java.net.SocketInputStream.read(SocketInputStream.java:140)
at java.base/sun.nio.cs.StreamDecoder.readBytes(StreamDecoder.java:284)
at java.base/sun.nio.cs.StreamDecoder.implRead(StreamDecoder.java:326)
at java.base/sun.nio.cs.StreamDecoder.read(StreamDecoder.java:178)
at java.base/java.io.InputStreamReader.read(InputStreamReader.java:181)
at java.base/java.io.BufferedReader.fill(BufferedReader.java:161)
at java.base/java.io.BufferedReader.readLine(BufferedReader.java:326)
at java.base/java.io.BufferedReader.readLine(BufferedReader.java:392)
at Gopher.sendCmd(Gopher.java:149)
at Gopher.main(Gopher.java:110)

SSH认证失败异常

com.jcraft.jsch.JSchException: Auth fail
at com.jcraft.jsch.Session.connect(Session.java:519)
at com.jcraft.jsch.Session.connect(Session.java:183)
at com.networkInterface.SshWorker5.doConnect3(SshWorker5.java:235)
at com.simpleSw.ossgw.connectionDaemon.command.CfiCmdV3.execute(CfiCmdV3.java:2663)
at com.simpleSw.ossgw.connectionDaemon.Connection.run(Connection.java:71)
at com.simpleSw.ossgw.connectionDaemon.DaemonThread$ConnectionThread.run(DaemonThread.java:90)
at java.base/java.lang.Thread.run(Thread.java:834)

执行流程

  • Shell程序发送请求;
  • Shell将请求转发给Java客户端(Gopher.java);
  • 客户端从4个监听的Socket服务中选择一个发送请求;
  • Socket服务接收请求,尝试通过SSH连接到请求指定的服务器;
  • 执行session.connect()时,客户端抛出SocketTimeoutException,发起请求的Shell进程终止,无法得知session.connect()内部的执行情况;
  • 数秒后出现Auth fail异常,但客户端已经超时,无法接收该信息。

相关代码

客户端发送请求代码

try {
    SocketAddress sockaddr = new InetSocketAddress(getHostName(), getPort());

    NetIntSocket = new Socket();

    NetIntSocket.connect(sockaddr, 5000);

    NetIntSocket.setSoTimeout(getTolerance());

    socketOut = new PrintWriter(NetIntSocket.getOutputStream(), true);
    socketIn = new BufferedReader(new InputStreamReader(NetIntSocket.getInputStream()));

    socketOut.println(getCommand());
    String line;
    boolean isUDC = isHLRUDC(getCommand());
    while ((line = socketIn.readLine()) != null) {
        if (isUDC) {
            Pattern pattern = Pattern.compile("EPDPIND   EPDPADD|        NO");
            Matcher matcher = pattern.matcher(line);
            if (!matcher.find())
                System.out.println(line);
        } else {
            System.out.println(line);
        }
    }

    return true;

SSH连接代码

public boolean doConnect3(String sshusr, String sship, String sshpwd, String command, PrintWriter out) throws JSchException, IOException {
    String result="";
    String result2="";

    try {
        JSch jSch = new JSch();
        session = jSch.getSession(sshusr, sship, port);
        session.setPassword(sshpwd);
        
        Properties config = new Properties();
        config.put("StrictHostKeyChecking", "no");
        session.setConfig(config);
        session.setTimeout(timeout);
        out.println("Antes session.conect timeout ["+timeout+"]");
        session.connect();     // 此处触发异常
        out.println("Despues session.conect timeout ["+timeout+"]");
        
        channel = session.openChannel("shell");
        channel.connect();

        expect = new ExpectBuilder()
                .withOutput(channel.getOutputStream())
                .withInputs(channel.getInputStream(), channel.getExtInputStream())
                //.withEchoOutput(System.out)
                //.withEchoInput(System.err)
                .build();       

        // out.println("Entro al try doConnect3.expect ["+channel.isConnected()+"]");
        return channel.isConnected();
    } catch (JSchException e) {
        e.printStackTrace();
        out.println("JSchException out [ "+e+" ]");
        System.out.println("JSchException System.out [ "+e+" ]");
        Logger.getLogger(SshWorker5.class.getName()).log(Level.SEVERE, "JSchException:", e.getMessage());
        out.println("JSchException getMessage() [ "+e.getMessage()+" ]");
        out.println("JSchException getCause() [ "+e.getCause()+" ]");
        out.println("JSchException getStackTrace() [ "+e.getStackTrace().toString()+" ]");
        return false;
    } catch (Exception e) {
        // out.println("Exception [ "+e.getMessage()+" ]");
        e.printStackTrace();
        Logger.getLogger(SshWorker5.class.getName()).log(Level.SEVERE, "SshConnectionException:", e);
    }
    // out.println("Entro al try doConnect3.catch ["+channel.isConnected()+"]");
    return false;
}

调用SSH连接的代码片段

if (sshSlave5.doConnect3(apgdata[1], apgdata[0], apgdata[2], MmlNe[0], out)) {
    out.println("");
    out.println("<<<<< " + MmlNe[1] + " >>>>>>");
    out.println("");
    out.println("<" + MmlNe[0]);
    out.flush();
    pod = sshSlave5.executeCommand(MmlNe[0], out);
    // out.println("Saliendo de sshSlave5.executeCommand ["+pod+"]");
    sshSlave5.disconnect();;
    out.println(pod);
    doPMlog(MmlNe[1], MmlNe[0], initTime, "YES", Integer.toString(ActiveQueries), "Executed");
} else {
    pod = ServantData.getACCESSERRMSG();
    pod = pod + "\\nOSS connectionStatus [" + qryRS + "]";
    out.println(pod);
    out.flush();
    doPMlog(MmlNe[1], MmlNe[0], initTime, "NOT", Integer.toString(ActiveQueries), "ACCESSERRMSG");
}

疑问

这是否是JSch的Bug?可能的原因是什么?

内容的提问来源于stack exchange,提问作者cblas

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.28 21:35:05