背景
由于我们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忽略证书.