的Android棒棒糖预设备给错误“SSL握手中止:SSL = 0x618d9c18:系统调用,通过对等连接复位期间I/O错误”

问题描述:

荫有这个奇怪的问题,其中改造不断抛出我的Android棒棒糖预设备给错误“SSL握手中止:SSL = 0x618d9c18:系统调用,通过对等连接复位期间I/O错误”

“SSL握手中止:SSL = 0x618d9c18:系统调用,由对等 连接复位期间I/O错误”

在奇巧

,而相同的代码在棒棒糖设备工作正常。 IAM使用OkHttpClient客户像下面

public OkHttpClient getUnsafeOkHttpClient() { 
    try { 
     final TrustManager[] trustAllCerts = new TrustManager[] { new X509TrustManager() { 
      @Override 
      public void checkClientTrusted(
        java.security.cert.X509Certificate[] chain, 
        String authType) { 
      } 
      @Override 
      public void checkServerTrusted(
        java.security.cert.X509Certificate[] chain, 
        String authType) { 
      } 
      @Override 
      public java.security.cert.X509Certificate[] getAcceptedIssuers() { 
       return new java.security.cert.X509Certificate[0]; 
      } 
     } }; 

     int cacheSize = 10 * 1024 * 1024; // 10 MB 
     Cache cache = new Cache(getCacheDir(), cacheSize); 
     final SSLContext sslContext = SSLContext.getInstance("TLSv1.2"); 
     sslContext.init(null, trustAllCerts, 
       new java.security.SecureRandom()); 
     final SSLSocketFactory sslSocketFactory = sslContext 
       .getSocketFactory(); 
     OkHttpClient okHttpClient = new OkHttpClient(); 
     okHttpClient = okHttpClient.newBuilder() 
       .cache(cache) 
       .sslSocketFactory(sslSocketFactory) 
       .hostnameVerifier(org.apache.http.conn.ssl.SSLSocketFactory.ALLOW_ALL_HOSTNAME_VERIFIER).build(); 
     return okHttpClient; 
    } catch (Exception e) { 
     throw new RuntimeException(e); 
    } 

} 

荫使用该客户端在改造这样

Retrofit retrofit = new Retrofit.Builder() 
      .baseUrl(URL) 
      .client(getUnsafeOkHttpClient()) 
      .addConverterFactory(GsonConverterFactory.create()) 
      .build(); 

编辑:添加getUnsafeOkHttpClient()在这里有没有影响

FYI:发行固定后这个崩溃被修复了Caused by: java.lang.IllegalStateException: Unable to extract the trust manager on [email protected], sslSocketFactory is class navneet.com.devinered.service.TLSSocketFactory

+0

你有使用TLSv1.2工作?如果您使用默认值,会怎么样? – algrid

+0

@algrid没有任何影响,如果我更改ssl实例,所以我删除了整个不安全的客户端改造,仍然只适用于棒棒糖,而不是kitkat –

+0

你的服务器端有什么?也许你可以从你的服务器上获取一些日志? – algrid

终于找到了解决这个问题,它不是一个完整的解决方案是通过Jesse Wilsonokhttp,方here提到的黑客攻击。正如我所说,这是一个简单的黑客,我不得不对我SSLSocketFactory的变量重命名为

private SSLSocketFactory delegate; 

通知,如果你给比委托其他任何名称,将抛出错误。荫张贴我下面

完整的解决方案这是我TLSSocketFactory

public class TLSSocketFactory extends SSLSocketFactory { 

private SSLSocketFactory delegate; 

public TLSSocketFactory() throws KeyManagementException, NoSuchAlgorithmException { 
    SSLContext context = SSLContext.getInstance("TLS"); 
    context.init(null, null, null); 
    delegate = context.getSocketFactory(); 
} 

@Override 
public String[] getDefaultCipherSuites() { 
    return delegate.getDefaultCipherSuites(); 
} 

@Override 
public String[] getSupportedCipherSuites() { 
    return delegate.getSupportedCipherSuites(); 
} 

@Override 
public Socket createSocket() throws IOException { 
    return enableTLSOnSocket(delegate.createSocket()); 
} 

@Override 
public Socket createSocket(Socket s, String host, int port, boolean autoClose) throws IOException { 
    return enableTLSOnSocket(delegate.createSocket(s, host, port, autoClose)); 
} 

@Override 
public Socket createSocket(String host, int port) throws IOException, UnknownHostException { 
    return enableTLSOnSocket(delegate.createSocket(host, port)); 
} 

@Override 
public Socket createSocket(String host, int port, InetAddress localHost, int localPort) throws IOException, UnknownHostException { 
    return enableTLSOnSocket(delegate.createSocket(host, port, localHost, localPort)); 
} 

@Override 
public Socket createSocket(InetAddress host, int port) throws IOException { 
    return enableTLSOnSocket(delegate.createSocket(host, port)); 
} 

@Override 
public Socket createSocket(InetAddress address, int port, InetAddress localAddress, int localPort) throws IOException { 
    return enableTLSOnSocket(delegate.createSocket(address, port, localAddress, localPort)); 
} 

private Socket enableTLSOnSocket(Socket socket) { 
    if(socket != null && (socket instanceof SSLSocket)) { 
     ((SSLSocket)socket).setEnabledProtocols(new String[] {"TLSv1.1", "TLSv1.2"}); 
    } 
    return socket; 
} 

} 

,这是我如何与okhttp用它和改造

OkHttpClient client=new OkHttpClient(); 
    try { 
     client = new OkHttpClient.Builder() 
       .sslSocketFactory(new TLSSocketFactory()) 
       .build(); 
    } catch (KeyManagementException e) { 
     e.printStackTrace(); 
    } catch (NoSuchAlgorithmException e) { 
     e.printStackTrace(); 
    } 

    Retrofit retrofit = new Retrofit.Builder() 
      .baseUrl(URL) 
      .client(client) 
      .addConverterFactory(GsonConverterFactory.create()) 
      .build(); 

我在这里获得了api.data.gov.in的SSL/TLS信息 - https://www.ssllabs.com/ssltest/analyze.html?d=api.data.gov.in

它看起来像只支持TLSv1.2。旧的Android版本确实与最新的TLS版本有关。在ssllabs页面的“Handshake Simulation”一节中,您甚至可以看到您的问题。

有关可用解决方案,请参阅How to enable TLS 1.2 support in an Android application (running on Android 4.1 JB)

+0

它没有为我工作,它现在崩溃与'引起:java.lang.IllegalStateException:无法提取信任管理器[email protected],sslSocketFactory是类navneet.com.devinered.service.TLSSocketFactory ' –