//基于okhttp3

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
OkHttpClient.Builder builder = new OkHttpClient.Builder();
builder.sslSocketFactory(new SSLSocketFactory() {
...
...
@Override
public Socket createSocket(Socket s, String host, int port, boolean autoClose) throws IOException {
//此方法为真正创建SSL Socket的地方
SSLCertificateSocketFactory sslSocketFactory =
(SSLCertificateSocketFactory) SSLCertificateSocketFactory
.getInsecure(0,null);
SSLSocket sslSocket = (SSLSocket) sslSocketFactory
.createSocket(s, host, port, autoClose);
sslSocket.setEnabledProtocols(sslSocket.getSupportedProtocols());

//method 1, 直接设置SNIHostName, API 24及以上支持
SSLParameters parameters = new SSLParameters();
SNIHostName sniHostName = new SNIHostName("sni.cashzhang.com");
List list = new ArrayList<SNIHostName>();
list.add(sniHostName);
parameters.setServerNames(list);
sslSocket.setSSLParameters(parameters);

//method 2, Hook SSLSocket.setHostname(p1)方法
try {
Method method = sslSocket.getClass().getMethod("setHostname", String.class);
method.invoke(sslSocket, "sni.cashzhang.com");
} catch (Exception ex) {
}

//method 3, 通过SSLCertificateSocketFactory::setHostname(p1, p2),API 17及以上支持
sslSocketFactory.setHostname(sslSocket, "sni.cashzhang.com");

return sslSocket;
}
...
...
})

改写OkHttp3源码,手动重新编译提取Jar

1
2
3
4
5
6
7
8
9
10
11
12
13
14
okhttp/okhttp/src/main/java/okhttp3/internal/connection/RealConnection.java
private void connectTls(ConnectionSpecSelector connectionSpecSelector) throws IOException{
...
...
if (connectionSpec.supportsTlsExtensions()) {
platform.get().configureTlsExtensions(
sslSocket, /*address.url().host()*/ null, address.protocols());
//AndroidPlatform::configureTlsExtensions(p1, p2, p3)中,若p2(address.url().host())不为空
//即支持TLS拓展,请求目标host非IP地址形式,会为此socket设置server_name
//为实现手动指定server_name,修改此处
}
...
...
}