Android 7.0:'javax.net.ssl.SSLHandshakeException:由对等关闭的连接

问题描述:

当我尝试从我的应用程序访问'https'Web服务时,它给出'javax.net.ssl.SSLHandshakeException:Connection由同行关闭'错误。相同的Web服务可以在Chrome浏览器中正常工作。Android 7.0:'javax.net.ssl.SSLHandshakeException:由对等关闭的连接

此问题仅在Android 7.0上发生,它在Android 6.0中正常工作& 5.0。

服务器通过CA认证,不是自签名的。

我不得不使用扩展的SSLSocket类包括所有协议和密码套件,以解决这个问题。该解决方案在于GetProtocolList()& GetCipherList()

private static OkHttpClient.Builder enableAllProtocols(OkHttpClient.Builder client) { 
    try { 
     client.sslSocketFactory(new SSLSocketFactoryExtended(), provideX509TrustManager()); 
    } catch (Exception exc) { 
     Log.e("OkHttpTLSCompat", "Error while setting Protocols", exc); 
    } 
    return client; 
} 

SSLSocketFactorExtended类文件

public class SSLSocketFactoryExtended extends SSLSocketFactory 

{ 
    private SSLContext mSSLContext; 
    private String[] mCiphers; 
    private String[] mProtocols; 

public SSLSocketFactoryExtended() throws NoSuchAlgorithmException, KeyManagementException 
{ 
    initSSLSocketFactoryEx(null,null,null); 
} 

public String[] getDefaultCipherSuites() 
{ 
    return mCiphers; 
} 

public String[] getSupportedCipherSuites() 
{ 
    return mCiphers; 
} 

public Socket createSocket(Socket s, String host, int port, boolean autoClose) throws IOException 
{ 
    SSLSocketFactory factory = mSSLContext.getSocketFactory(); 
    SSLSocket ss = (SSLSocket)factory.createSocket(s, host, port, autoClose); 

    ss.setEnabledProtocols(mProtocols); 
    ss.setEnabledCipherSuites(mCiphers); 

    return ss; 
} 

public Socket createSocket(InetAddress address, int port, InetAddress localAddress, int localPort) throws IOException 
{ 
    SSLSocketFactory factory = mSSLContext.getSocketFactory(); 
    SSLSocket ss = (SSLSocket)factory.createSocket(address, port, localAddress, localPort); 

    ss.setEnabledProtocols(mProtocols); 
    ss.setEnabledCipherSuites(mCiphers); 

    return ss; 
} 

@Override 
public Socket createSocket(String host, int port, InetAddress localHost, int localPort) throws IOException 
{ 
    SSLSocketFactory factory = mSSLContext.getSocketFactory(); 
    SSLSocket ss = (SSLSocket)factory.createSocket(host, port, localHost, localPort); 

    ss.setEnabledProtocols(mProtocols); 
    ss.setEnabledCipherSuites(mCiphers); 

    return ss; 
} 

@Override 
public Socket createSocket(InetAddress host, int port) throws IOException 
{ 
    SSLSocketFactory factory = mSSLContext.getSocketFactory(); 
    SSLSocket ss = (SSLSocket)factory.createSocket(host, port); 

    ss.setEnabledProtocols(mProtocols); 
    ss.setEnabledCipherSuites(mCiphers); 

    return ss; 
} 

@Override 
public Socket createSocket(String host, int port) throws IOException 
{ 
    SSLSocketFactory factory = mSSLContext.getSocketFactory(); 
    SSLSocket ss = (SSLSocket)factory.createSocket(host, port); 

    ss.setEnabledProtocols(mProtocols); 
    ss.setEnabledCipherSuites(mCiphers); 

    return ss; 
} 

private void initSSLSocketFactoryEx(KeyManager[] km, TrustManager[] tm, SecureRandom random) 
     throws NoSuchAlgorithmException, KeyManagementException 
{ 
    mSSLContext = SSLContext.getInstance("TLS"); 
    mSSLContext.init(km, tm, random); 

    mProtocols = GetProtocolList(); 
    mCiphers = GetCipherList(); 
} 

protected String[] GetProtocolList() 
{ 
    String[] protocols = { "TLSv1", "TLSv1.1", "TLSv1.2", "TLSv1.3"}; 
    String[] availableProtocols = null; 

    SSLSocket socket = null; 

    try 
    { 
     SSLSocketFactory factory = mSSLContext.getSocketFactory(); 
     socket = (SSLSocket)factory.createSocket(); 

     availableProtocols = socket.getSupportedProtocols(); 
    } 
    catch(Exception e) 
    { 
     return new String[]{ "TLSv1" }; 
    } 
    finally 
    { 
     if(socket != null) 
      try { 
       socket.close(); 
      } catch (IOException e) { 
      } 
    } 

    List<String> resultList = new ArrayList<String>(); 
    for(int i = 0; i < protocols.length; i++) 
    { 
     int idx = Arrays.binarySearch(availableProtocols, protocols[i]); 
     if(idx >= 0) 
      resultList.add(protocols[i]); 
    } 

    return resultList.toArray(new String[0]); 
} 

protected String[] GetCipherList() 
{ 
    List<String> resultList = new ArrayList<String>(); 
    SSLSocketFactory factory = mSSLContext.getSocketFactory(); 
    for(String s : factory.getSupportedCipherSuites()){ 
     resultList.add(s); 
    } 
    return resultList.toArray(new String[resultList.size()]); 
} 

}

尝试使用此代码,它为我工作:

​​

,不要忘记到usr谷歌安全库:

compile 'com.google.android.gms:play-services-safetynet:11.6.2'