天天看點

com.android.volley.NoConnectionError: javax.net.ssl.SSLHandshakeException: Handshake failed

上班上的好好的,一個其他部門的同僚來着手機來說,APP在他的手機上登入不進去。
 實在是最近沒有進行更新,在其他手機上也是好好的呀 ~~~
 然後他說他以前也是好的,最近手機更新了一次。一檢視版本,Android6.0(小米4);


 然後測試了一下三星6.0,Nexus6.0的結果都進不去,Android5.0,Android4.0的都
 沒有問題,是以應該是Android6.0Google對其進行了一些修改。

 debug後發現重寫的parseNetworkResponse()方法進不去。是以請求網絡傳回的資料無法解析。
 然後跟蹤到源碼。發現NetworkDispatcher.java這個類裡面
           
com.android.volley.NoConnectionError: javax.net.ssl.SSLHandshakeException: Handshake failed

進入到了VolleyError裡面。

報錯com.android.volley.NoConnectionError: javax.net.ssl.SSLHandshakeException: Handshake failed

其實如果不是用的https用http的話就不會有這樣的問題。因為本身我們的代碼是對https的通路做過處理了的。

public class _FakeX509TrustManager implements X509TrustManager {

    private static TrustManager[] trustManagers;
    private static final X509Certificate[] _AcceptedIssuers = new X509Certificate[] {};

    public boolean isClientTrusted(X509Certificate[] chain) {
        return true;
    }

    public boolean isServerTrusted(X509Certificate[] chain) {
        return true;
    }

    /**
     * 允許所有SSL連接配接 調用此方法,可以解決Not trusted server certificate異常
     */
    public static void allowAllSSL() {
        HttpsURLConnection.setDefaultHostnameVerifier(new HostnameVerifier() {

            public boolean verify(String s, SSLSession sslsession) {

                return true;
            }

        });

        SSLContext context = null;
        if (trustManagers == null) {
            trustManagers = new TrustManager[] { new _FakeX509TrustManager() };
        }

        try {
            context = SSLContext.getInstance("TLS");
            context.init(null, trustManagers, new SecureRandom());
        } catch (NoSuchAlgorithmException e) {
            e.printStackTrace();
        } catch (KeyManagementException e) {
            e.printStackTrace();
        }

        HttpsURLConnection.setDefaultSSLSocketFactory(context
                .getSocketFactory());
    }

    public void checkClientTrusted(X509Certificate[] ax509certificate, String s)
            throws java.security.cert.CertificateException {

    }

    public void checkServerTrusted(X509Certificate[] ax509certificate, String s)
            throws java.security.cert.CertificateException {

    }

    public X509Certificate[] getAcceptedIssuers() {
        return _AcceptedIssuers;
    }
}
           

是以在想不應該出現這個問題啊。。

那麼在Android6.0以下的版本和非https的通路路徑不會有問題的話。

這樣是不是可以總結為Android6.0對https的通路做了修改呢???

檢視資料發現:

Google 現在用BoringSSL 代替了OpenSSL ,而且開始應用到一些Google産品,AndroidM就

開始采用的BoringSSL。是以就找到問題的所在了~~

Tomcat伺服器側的SSL/TLS配置存在安全漏洞導緻Android6.0上的BoringSSL報錯!!!

SSL/TLS握手過程中,假如選中了諸如TLS_DHE_RSA_WITH_AES_128_CBC_SHA這樣使用deffie-hellman密鑰的cipher,那麼在deffie-hellman密鑰交換過程中會使用的一個P參數(prime number),伺服器側提供的P參數在JDK8之前都隻用了768bit的長度,小于1024bit存在安全漏洞可導緻logjam attack,會被最新本版的浏覽器和BoringSSL拒絕。

最後最後的解決方式是:

讓背景在伺服器的Tomcat 的server.xml的connector配置裡顯示聲明使用哪些cipher來排除用到deffie-hellman密鑰的,加上一下配置 :

<Connector port="443" SSLEnabled="true" sslProtocol="TLS"
 ciphers="TLS_RSA_WITH_AES_128_CBC_SHA256,
          TLS_RSA_WITH_AES_128_CBC_SHA,
          TLS_RSA_WITH_AES_256_CBC_SHA256,
          TLS_RSA_WITH_AES_256_CBC_SHA,
          SSL_RSA_WITH_3DES_EDE_CBC_SHA"
…… />
           

最後問題就解決了。。。

看别人說将Tomact的JDK更新到8也闊以,,,這個就沒有試了。

對了,Android6.0删除了HttpClient的相關類~~

android 6.0(api 23) SDK,不再提供org.apache.http.*(隻保留幾個類).

可以在libs中加入

org.apache.http.legacy.jar

或者直接在相應的module下的build.gradle中加入:

android {

useLibrary ‘org.apache.http.legacy’

}

注意放置的位置:是在android {}中