Skip to content

Commit add5373

Browse files
authored
Merge pull request #1032 from didi/bugfix/3.6.x_all
fix:修改兼容自定义 SSLSocketFactory 导致的网络拦截 OkHttp is unable to extract the …
2 parents 4faf645 + 603036f commit add5373

File tree

2 files changed

+132
-6
lines changed

2 files changed

+132
-6
lines changed
Lines changed: 125 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,125 @@
1+
package com.didichuxing.doraemonkit.aop.urlconnection;
2+
3+
import java.lang.reflect.Field;
4+
import java.security.SecureRandom;
5+
import java.security.cert.CertificateException;
6+
import java.security.cert.X509Certificate;
7+
8+
import javax.annotation.Nullable;
9+
import javax.net.ssl.SSLContext;
10+
import javax.net.ssl.SSLSocketFactory;
11+
import javax.net.ssl.X509TrustManager;
12+
13+
/**
14+
* didi Create on 2022/5/24 .
15+
* <p>
16+
* Copyright (c) 2022/5/24 by didiglobal.com.
17+
*
18+
* @author <a href="realonlyone@126.com">zhangjun</a>
19+
* @version 1.0
20+
* @Date 2022/5/24 5:34 下午
21+
* @Description 用一句话说明文件功能
22+
*/
23+
24+
public class MyTrustManager {
25+
26+
27+
private static final X509TrustManager trustManager = new X509TrustManager() {
28+
@Override
29+
public void checkClientTrusted(X509Certificate[] chain, String authType) throws CertificateException {
30+
31+
}
32+
33+
@Override
34+
public void checkServerTrusted(X509Certificate[] chain, String authType) throws CertificateException {
35+
36+
}
37+
38+
@Override
39+
public X509Certificate[] getAcceptedIssuers() {
40+
return new X509Certificate[0];
41+
}
42+
};
43+
44+
public X509TrustManager getTrustManager() {
45+
return trustManager;
46+
}
47+
48+
public X509TrustManager buildTrustManager() {
49+
SSLContext sslContext = null;
50+
try {
51+
sslContext = SSLContext.getInstance("TLS");
52+
sslContext.init(null, new X509TrustManager[]{trustManager}, new SecureRandom());
53+
SSLSocketFactory ssl = sslContext.getSocketFactory();
54+
return trustManager(ssl);
55+
} catch (Exception e) {
56+
e.printStackTrace();
57+
}
58+
return null;
59+
}
60+
61+
62+
private X509TrustManager trustManager2(SSLSocketFactory sslSocketFactory) {
63+
// Attempt to get the trust manager from an OpenJDK socket factory. We attempt this on all
64+
// platforms in order to support Robolectric, which mixes classes from both Android and the
65+
// Oracle JDK. Note that we don't support HTTP/2 or other nice features on Robolectric.
66+
try {
67+
Class<?> sslContextClass = Class.forName("sun.security.ssl.SSLContextImpl");
68+
Object context = readFieldOrNull(sslSocketFactory, sslContextClass, "context");
69+
if (context == null) return null;
70+
return readFieldOrNull(context, X509TrustManager.class, "trustManager");
71+
} catch (ClassNotFoundException e) {
72+
return null;
73+
}
74+
}
75+
76+
private X509TrustManager trustManager(SSLSocketFactory sslSocketFactory) throws Exception {
77+
78+
Class sslParametersClass = Class.forName("com.android.org.conscrypt.SSLParametersImpl");
79+
Class sslSocketClass = Class.forName("com.android.org.conscrypt.OpenSSLSocketImpl");
80+
81+
Object context = readFieldOrNull(sslSocketFactory, sslParametersClass, "sslParameters");
82+
if (context == null) {
83+
// If that didn't work, try the Google Play Services SSL provider before giving up. This
84+
// must be loaded by the SSLSocketFactory's class loader.
85+
try {
86+
Class<?> gmsSslParametersClass = Class.forName(
87+
"com.google.android.gms.org.conscrypt.SSLParametersImpl", false,
88+
sslSocketFactory.getClass().getClassLoader());
89+
context = readFieldOrNull(sslSocketFactory, gmsSslParametersClass, "sslParameters");
90+
} catch (ClassNotFoundException e) {
91+
return trustManager2(sslSocketFactory);
92+
}
93+
}
94+
95+
X509TrustManager x509TrustManager = readFieldOrNull(
96+
context, X509TrustManager.class, "x509TrustManager");
97+
if (x509TrustManager != null) return x509TrustManager;
98+
99+
return readFieldOrNull(context, X509TrustManager.class, "trustManager");
100+
}
101+
102+
static @Nullable
103+
<T> T readFieldOrNull(Object instance, Class<T> fieldType, String fieldName) {
104+
for (Class<?> c = instance.getClass(); c != Object.class; c = c.getSuperclass()) {
105+
try {
106+
Field field = c.getDeclaredField(fieldName);
107+
field.setAccessible(true);
108+
Object value = field.get(instance);
109+
if (!fieldType.isInstance(value)) return null;
110+
return fieldType.cast(value);
111+
} catch (NoSuchFieldException ignored) {
112+
} catch (IllegalAccessException e) {
113+
throw new AssertionError();
114+
}
115+
}
116+
117+
// Didn't find the field we wanted. As a last gasp attempt, try to find the value on a delegate.
118+
if (!fieldName.equals("delegate")) {
119+
Object delegate = readFieldOrNull(instance, Object.class, "delegate");
120+
if (delegate != null) return readFieldOrNull(delegate, fieldType, fieldName);
121+
}
122+
123+
return null;
124+
}
125+
}

Android/dokit/src/main/java/com/didichuxing/doraemonkit/aop/urlconnection/ObsoleteUrlFactory.java

Lines changed: 7 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -6,11 +6,8 @@
66
import androidx.annotation.Nullable;
77
import androidx.annotation.RequiresApi;
88

9-
import com.didichuxing.doraemonkit.kit.network.utils.StreamUtil;
109
import com.didichuxing.doraemonkit.util.ConvertUtils;
11-
import com.didichuxing.doraemonkit.util.LogHelper;
1210

13-
import java.io.FileNotFoundException;
1411
import java.io.IOException;
1512
import java.io.InputStream;
1613
import java.io.InterruptedIOException;
@@ -49,6 +46,7 @@
4946
import javax.net.ssl.HostnameVerifier;
5047
import javax.net.ssl.HttpsURLConnection;
5148
import javax.net.ssl.SSLSocketFactory;
49+
import javax.net.ssl.X509TrustManager;
5250

5351
import okhttp3.Call;
5452
import okhttp3.Callback;
@@ -1313,12 +1311,15 @@ public void setSSLSocketFactory(SSLSocketFactory sslSocketFactory) {
13131311
if (sslSocketFactory == null) {
13141312
throw new IllegalArgumentException("sslSocketFactory == null");
13151313
}
1314+
1315+
X509TrustManager trustManager = new MyTrustManager().getTrustManager();
13161316
// This fails in JDK 9 because OkHttp is unable to extract the trust manager.
13171317
delegate.client = delegate.client.newBuilder()
1318-
.sslSocketFactory(sslSocketFactory)
1319-
.build();
1318+
.sslSocketFactory(sslSocketFactory, trustManager)
1319+
.build();
13201320
}
13211321

1322+
13221323
@Override
13231324
public SSLSocketFactory getSSLSocketFactory() {
13241325
return delegate.client.sslSocketFactory();
@@ -1342,4 +1343,4 @@ public Response intercept(Chain chain) throws IOException {
13421343
}
13431344
}
13441345

1345-
}
1346+
}

0 commit comments

Comments
 (0)