Android https忽略证书问题

1,300 阅读2分钟

背景

由于我们https url的一个证书过期了,导致有些https的请求无法返回,但是奇怪的是主进程的请求正常,但是其他进程的请求由于证书过期无法返回.

探索

一般情况下如果证书过期,访问的时候会报下面的错误

javax.net.ssl.SSLHandshakeException: Chain validation failed

这时候设置忽略证书访问就ok了

private static class TrustAllCerts implements X509TrustManager {
    @Override
    public void checkClientTrusted(X509Certificate[] x509Certificates, String s) throws CertificateException {
    }

    @Override
    public void checkServerTrusted(X509Certificate[] x509Certificates, String s) throws CertificateException {

    }

    @Override
    public X509Certificate[] getAcceptedIssuers() {
        return new X509Certificate[0];
    }
}

private static SSLSocketFactory createSSLSocketFactory() {
    SSLSocketFactory ssfFactory = null;
    try {
        SSLContext sc = SSLContext.getInstance("TLS");
        sc.init(null, new TrustManager[]{new TrustAllCerts()}, new SecureRandom());
        ssfFactory = sc.getSocketFactory();
    } catch (Exception e) {
    }
    return ssfFactory;
}


URL url = new URL("https://www.xxx.xxx");
HttpsURLConnection connection = (HttpsURLConnection) url.openConnection();
connection.setSSLSocketFactory(createSSLSocketFactory());
connection.setHostnameVerifier(new HostnameVerifier() {
    @Override
    public boolean verify(String hostname, SSLSession session) {
        return true;
    }
});

奇怪的事情是,我们请求的代码里面并没有类似的代码,主进程应该和其他进程一致都无法访问才对,为什么单单主进程能访问成功呢?

Android系统应该是不会针对一个应用的不同进程做这种处理,怀疑是不是有个地方设置了全局的忽略证书,全局的忽略应该这样设置

HttpsURLConnection.setDefaultSSLSocketFactory();
HttpsURLConnection.setDefaultHostnameVerifier();

jadx反编译我们的apk,com.tencent.bugly.proguard.s找到了下面的代码

TrustManager[] trustManagerArr = {new X509TrustManager() { // from class: com.tencent.bugly.proguard.s.1
            @Override // javax.net.ssl.X509TrustManager
            public final X509Certificate[] getAcceptedIssuers() {
                return new X509Certificate[0];
            }

            @Override // javax.net.ssl.X509TrustManager
            public final void checkClientTrusted(X509Certificate[] x509CertificateArr, String str3) {
                y.c("checkClientTrusted", new Object[0]);
            }

            @Override // javax.net.ssl.X509TrustManager
            public final void checkServerTrusted(X509Certificate[] x509CertificateArr, String str3) {
                y.c("checkServerTrusted", new Object[0]);
            }
        }};
        try {
            SSLContext instance = SSLContext.getInstance("TLS");
            instance.init(null, trustManagerArr, new SecureRandom());
            HttpsURLConnection.setDefaultSSLSocketFactory(instance.getSocketFactory());
        } catch (Exception e) {
            e.printStackTrace();
        }

有理由怀疑这段代码导致了我们的问题,而且我们确实设置了主进程为Bugly的Upload进程,更确信是Bugly导致的问题.
经过测试,确实我们设置哪个进程为Bugly的Upload进程,哪个进程就可以忽略证书,其他进程就无法访问.

结论

Bugly会设置Upload的进程忽略https证书验证.最新版本的Bugly我没有测试,不确定Bugly是否修改了此问题.一般来说,第三方sdk不应该设置全局的https忽略证书.