关于Okhttp 报javax.net.ssl.SSLHandshakeException: Handshake failed

一、问题

最近把环境切换到灰度环境,有一个接口一直报“javax.net.ssl.SSLHandshakeException: Handshake failed”。

二、分析

看这个描述,是网络连接时握手失败。这下不得不跟到源码里看了,联想到OkHttp的网络请求流程,出问题的地方应该是网络连接的地方出了问题,即ConnectInterceptor,打断点跟进去,果然,在执行到

 HttpCodec httpCodec = streamAllocation.newStream(client, chain, doExtensiveHealthChecks);

出了异常,这里面涉及到一堆核心源码:

StreamAllocation.java

public HttpCodec newStream(
      OkHttpClient client, Interceptor.Chain chain, boolean doExtensiveHealthChecks) {
    
    
    int connectTimeout = chain.connectTimeoutMillis();
    int readTimeout = chain.readTimeoutMillis();
    int writeTimeout = chain.writeTimeoutMillis();
    int pingIntervalMillis = client.pingIntervalMillis();
    boolean connectionRetryEnabled = client.retryOnConnectionFailure();

    try {
    
    
      // 核心
      RealConnection resultConnection = findHealthyConnection(connectTimeout, readTimeout,
          writeTimeout, pingIntervalMillis, connectionRetryEnabled, doExtensiveHealthChecks);
      HttpCodec resultCodec = resultConnection.newCodec(client, chain, this);

      synchronized (connectionPool) {
    
    
        codec = resultCodec;
        return resultCodec;
      }
    } catch (IOException e) {
    
    
      throw new RouteException(e);
    }
  }

接下来就是往RealConnection类里跟代码,由于代码篇幅太大,这里我还是简单说下位置,在connectTls方法中,会去做htts的连接,里面就有相关的握手代码:

  // Force handshake. This can throw!
      sslSocket.startHandshake();
      // block for session establishment
      SSLSession sslSocketSession = sslSocket.getSession();
      if (!isValid(sslSocketSession)) {
    
    
        throw new IOException("a valid ssl session was not established");
      }
      Handshake unverifiedHandshake = Handshake.get(sslSocketSession);

然而,这样看似乎还是找不到答案,因为代码太长了,有个办法,看异常日志。Ok3里代码一旦出现异常,就喜欢抛异常日志,这里我把日志翻出来:
在这里插入图片描述
在这里插入图片描述
根据日志里提到的行号:okhttp3.internal.connection.RealConnection.connectTls(RealConnection.java:302)
确定了执行sslSocket.startHandshake();这句出现的问题,至于原因,上面的日志中也有提到:
在这里插入图片描述
啥意思?我也不知道,但结合上面的信息,我能猜出来出问题的方向,日志里反复提到
SSL
这个词,说明是https建立握手链接时出现了异常了。https链接出现异常有两种情况

  • 1、网络安全证书没有设置,就是这个X509TrustManager
  • 2、当前接口不支持服务端不支持https。

朝着这两个方向,我检查了代码,第一种情况排除。问题出现第二种情况,即当前的灰度地址不支持https!!!做安全优化时,服务端无视了灰度环境的安全优化。。。。

三、解决

让服务端改,或者我来把https换成http.

四、总结

这个问题充分验证了读源码的重要性,还好前两年我读过OK3的源码,对于网络执行的流程有个了解,这节省了我排查问题的时间,提升效率

猜你喜欢

转载自blog.csdn.net/qq_26439323/article/details/117226553