本文主旨是在不升级gradle版本和compile sdk的情况下解决https连接失败的问题
由于最近后台服务器升级,http改成https,而且使用的是Tlsv1.3 协议
导致了客户端https连接失败。
最初报的错误是sslv3 alert handshake failure
从网上找的方法是扩展SSLSocketFactory并设置,试了一下是可以的,但是报了新的错误protocol TLSv1.3 is not supported
原因是android自带的conscrypt不支持TLS1.3, 要用插件来支持,于是在gradle.build
里面添加
implementation 'org.conscrypt:conscrypt-android:2.2.1'
同时在application的oncreate里面调用
Security.insertProviderAt(Conscrypt.newProvider(), 1);
这样在设置扩展SSLSocketFactory 的时候就会使用新的Conscrypt模块,这样就完美解决了adnroid 4.4以下版本支持https TLSv1.3的问题。
总结一下:
1、gradle.build里面添加
implementation 'org.conscrypt:conscrypt-android:2.2.1'
2、application的oncreate里面调用
Security.insertProviderAt(Conscrypt.newProvider(), 1);
3、自定义 SSLSocketFactory
public class TlsSocketFactory extends SSLSocketFactory { private static final String[] TLS_SUPPORT_VERSION = {"TLSv1.1", "TLSv1.2", "TLSv1.3"}; final SSLSocketFactory delegate; public TlsSocketFactory(SSLSocketFactory base) { this.delegate = base; } @Override public String[] getDefaultCipherSuites() { return delegate.getDefaultCipherSuites(); } @Override public String[] getSupportedCipherSuites() { return delegate.getSupportedCipherSuites(); } @Override public Socket createSocket(Socket s, String host, int port, boolean autoClose)throws IOException { return patch(delegate.createSocket(s, host, port, autoClose)); } @Override public Socket createSocket(String host, int port)throws IOException, UnknownHostException { return patch(delegate.createSocket(host, port)); } @Override public Socket createSocket(String host, int port, InetAddress localHost, int localPort)throws IOException, UnknownHostException { return patch(delegate.createSocket(host, port, localHost, localPort)); } @Override public Socket createSocket(InetAddress host, int port)throws IOException { return patch(delegate.createSocket(host, port)); } @Override public Socket createSocket(InetAddress address, int port, InetAddress localAddress, int localPort)throws IOException { return patch(delegate.createSocket(address, port, localAddress, localPort)); } private Socket patch(Socket s) { if (s instanceof SSLSocket) { ((SSLSocket) s).setEnabledProtocols(TLS_SUPPORT_VERSION); } return s; } }
4、每次https连接时设置自定义的 SSLSocketFactory
URL url = new URL("https://xxxxxxxxx"); HttpsURLConnection conn = (HttpsURLConnection) url.openConnection(); SSLContext sslContext =null; try { sslContext = SSLContext.getInstance("TLS"); try { sslContext.init(null, null, null); }catch (KeyManagementException e) { e.printStackTrace(); } } catch (NoSuchAlgorithmException e) { e.printStackTrace(); } SSLSocketFactory socketFactory =new TlsSocketFactory(sslContext.getSocketFactory()); if (sslContext != null) { conn.setSSLSocketFactory(socketFactory); }