zoukankan      html  css  js  c++  java
  • https Android 5.0 以下TLS 版本过低造成的问题

     异常如下

    javax.net.ssl.SSLHandshakeException: javax.net.ssl.SSLProtocolException: SSL handshake aborted: ssl=0x610df808: Failure in SSL library, usually a protocol error
                                                    error:14077410:SSL routines:SSL23_GET_SERVER_HELLO:sslv3 alert handshake failure (external/openssl/ssl/s23_clnt.c:741 0x410f976a:0x00000000)
                                                        at org.apache.harmony.xnet.provider.jsse.OpenSSLSocketImpl.startHandshake(OpenSSLSocketImpl.java:412)
                                                        at okhttp3.internal.connection.RealConnection.connectTls(Paramount:281)
                                                        at okhttp3.internal.connection.RealConnection.establishProtocol(Paramount:251)
                                                        at okhttp3.internal.connection.RealConnection.connect(Paramount:151)
                                                        at okhttp3.internal.connection.StreamAllocation.findConnection(Paramount:192)
                                                        at okhttp3.internal.connection.StreamAllocation.findHealthyConnection(Paramount:121)
                                                        at okhttp3.internal.connection.StreamAllocation.newStream(Paramount:100)
                                                        at okhttp3.internal.connection.ConnectInterceptor.intercept(Paramount:42)
                                                        at okhttp3.internal.http.RealInterceptorChain.proceed(Paramount:92)
                                                        at okhttp3.internal.http.RealInterceptorChain.proceed(Paramount:67)
                                                        at okhttp3.internal.cache.CacheInterceptor.intercept(Paramount:93)
                                                        at okhttp3.internal.http.RealInterceptorChain.proceed(Paramount:92)
                                                        at okhttp3.internal.http.RealInterceptorChain.proceed(Paramount:67)
                                                        at okhttp3.internal.http.BridgeInterceptor.intercept(Paramount:93)
                                                        at okhttp3.internal.http.RealInterceptorChain.proceed(Paramount:92)
                                                        at okhttp3.internal.http.RetryAndFollowUpInterceptor.intercept(Paramount:120)
                                                        at okhttp3.internal.http.RealInterceptorChain.proceed(Paramount:92)
                                                        at okhttp3.internal.http.RealInterceptorChain.proceed(Paramount:67)
                                                        at okhttp3.RealCall.getResponseWithInterceptorChain(Paramount:185)
                                                        at okhttp3.RealCall.execute(Paramount:69)
                                                        at com.qihoo.mm.paramount.tools.glide.j.b(Paramount:44)
                                                        at com.qihoo.mm.paramount.tools.glide.j.a(Paramount:21)
                                                        at com.bumptech.glide.load.b.f$a.b(Paramount:70)
                                                        at com.bumptech.glide.load.b.f$a.a(Paramount:53)
                                                        at com.bumptech.glide.load.engine.a.e(Paramount:170)
                                                        at com.bumptech.glide.load.engine.a.c(Paramount:128)
                                                        at com.bumptech.glide.load.engine.h.f(Paramount:122)
                                                        at com.bumptech.glide.load.engine.h.d(Paramount:101)
                                                        at com.bumptech.glide.load.engine.h.run(Paramount:58)
                                                        at java.util.concurrent.Executors$RunnableAdapter.call(Executors.java:442)
                                                        at java.util.concurrent.FutureTask$Sync.innerRun(FutureTask.java:305)
                                                        at java.util.concurrent.FutureTask.run(FutureTask.java:137)
                                                        at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1076)
                                                        at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:569)
                                                        at java.lang.Thread.run(Thread.java:856)
                                                        at com.bumptech.glide.load.engine.executor.FifoPriorityThreadPoolExecutor$a$1.run(Paramount:118)
                                                     Caused by: javax.net.ssl.SSLProtocolException: SSL handshake aborted: ssl=0x610df808: Failure in SSL library, usually a protocol error
                                                    error:14077410:SSL routines:SSL23_GET_SERVER_HELLO:sslv3 alert handshake failure (external/openssl/ssl/s23_clnt.c:741 0x410f976a:0x00000000)
                                                        at org.apache.harmony.xnet.provider.jsse.NativeCrypto.SSL_do_handshake(Native Method)
                                                        at org.apache.harmony.xnet.provider.jsse.OpenSSLSocketImpl.startHandshake(OpenSSLSocketImpl.java:371)
                                                            ... 35 more

    由于集成的 SSL 库版本不同,不同 Android 版本的默认 SSL/TLS 版本配置如下表:

    ProtocolSupported (API Levels)Enabled by default (API Levels)
    SSLv3 1–TBD 1–22
    TLSv1 1+ 1+
    TLSv1.1 20+ 20+
    TLSv1.2 20+ 20+

    在 Android 5.0 之前,最高支持的 SSL/TLS 版本为 TLSv1,而这个版本实际上是一个安全性并不是太好的版本,当前已经有许多网站配置为不再支持这种老版本的 SSL/TLS 。在用 Android 5.0 之前的设备,访问一些不再支持 TLSv1 及之前 SSL/TLS 版本的网站的时候,就会出现一些问题。

     在 Android 4.3、Android 4.2.2 和 Android 4.1.1 上,用相同版本的 OkHttp 访问前面配置为最低支持 TLSv1.1 的 HTTP 服务器时,抛出了完全相同的异常。

    客户端版本低于服务器支持的最低 SSL/TLS 版本时,HTTPS 连接会在握手阶段失败。

     为请求的网络客户端设置一个特殊的SSLSocketFactory

    import android.os.Build
    import android.util.Log
    import com.android.core.Arrays
    import com.qihoo.mm.paramount.env.AppEnv
    import okhttp3.OkHttpClient
    import java.io.IOException
    import java.net.InetAddress
    import java.net.Socket
    import java.net.UnknownHostException
    import java.security.GeneralSecurityException
    import java.security.KeyStore
    import javax.net.ssl.*
    public class Tls12SocketFactory extends SSLSocketFactory {
        private static final String[] TLS_SUPPORT_VERSION = {"TLSv1.1", "TLSv1.2"};
    
        final SSLSocketFactory delegate;
    
        public Tls12SocketFactory(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;
        }
    }

    修改默认X509TrustManager 

     private X509TrustManager getDefaultTrustManager() {
        try {
          TrustManagerFactory trustManagerFactory = TrustManagerFactory.getInstance(
                  TrustManagerFactory.getDefaultAlgorithm());
          trustManagerFactory.init((KeyStore) null);
          TrustManager[] trustManagers = trustManagerFactory.getTrustManagers();
          if (trustManagers.length != 1 || !(trustManagers[0] instanceof X509TrustManager)) {
            throw new IllegalStateException("Unexpected default trust managers:"
                    + Arrays.toString(trustManagers));
          }
          return (X509TrustManager) trustManagers[0];
        } catch (GeneralSecurityException e) {
          throw new AssertionError(); // The system has no TLS. Just give up.
        }
      }

    设置OkHttpClient

     private OkHttpClient initOkHttpClient()  {
            OkHttpClient builder = OkHttpClient.Builder()
            try {
                if(DEBUG){
                    Log.i(TAG,"initOkHttpClient")
                }
                if (Build.VERSION.SDK_INT < Build.VERSION_CODES.LOLLIPOP) {
                    Tls12SocketFactory.enableTls12OnPreLollipop(builder)
                }
                builder.readTimeout(10L, TimeUnit.SECONDS)//设置读取超时时间
                builder.writeTimeout(10L, TimeUnit.SECONDS)//设置写的超时时间
                builder.connectTimeout(10L, TimeUnit.SECONDS)//设置连接超时时间
            } catch (e: Exception) {
                if(DEBUG){
                    Log.e(TAG,"",e)
                }
            }
            return builder.build()
        }
    
        public static OkHttpClient.Builder enableTls12OnPreLollipop(OkHttpClient.Builder client) {
            if (Build.VERSION.SDK_INT >= 16 && Build.VERSION.SDK_INT < 22) {
                
                  try {
                       val sslContext  = SSLContext.getInstance("TLS")
                        sslContext .init(null, null, null)
    
                        val socketFactory = Tls12SocketFactory(sslContext.socketFactory)
                        client.sslSocketFactory(socketFactory, getDefaultTrustManager())
    
                    } catch (exc: Exception) {
                        if (AppEnv.bAppdebug) {
                            Log.e("OkHttpTLSCompat", "Error while setting TLS 1.2", exc)
                        }
                try {
                    SSLContext sc = SSLContext.getInstance("TLSv1.2");
                    sc.init(null, null, null);
                    client.sslSocketFactory(new Tls12SocketFactory(sc.getSocketFactory()));
                   client.sslSocketFactory(socketFactory, getDefaultTrustManager())
    
    
                    client.connectionSpecs(specs);
                } catch (Exception exc) {
                    if (AppEnv.bAppdebug) {
                        Log.e("OkHttpTLSCompat", "Error while setting TLS 1.2", exc);
                    }
                }
            }
    
            return client;
        }
  • 相关阅读:
    获取项目路径
    Form提交时隐藏Token验证
    属性路由参数约束
    使用Cookie来统计浏览次数,当天重复刷新不增加
    图片上传预览 支持html5的浏览器
    icheck.min.js 选中效果
    bootstrap-modal.js 居中问题
    七十二、SAP中内表的修改,添加条件语句,多条目修改
    七十一、SAP中内表的修改,改一行数据,或一行的某个字段
    七十、SAP中内表批量指定位置插入
  • 原文地址:https://www.cnblogs.com/mingfeng002/p/8436416.html
Copyright © 2011-2022 走看看