使用okHttp信任所有证书

出于testing的目的,我试图添加一个套接字工厂到我的okHttp客户端,它设置代理时信任所有的东西。 这已经做了很多次,但我的信任套接字工厂的实现似乎是缺less的东西:

class TrustEveryoneManager implements X509TrustManager { @Override public void checkClientTrusted(java.security.cert.X509Certificate[] chain, String authType) throws CertificateException { } @Override public void checkServerTrusted(java.security.cert.X509Certificate[] chain, String authType) throws CertificateException { } @Override public java.security.cert.X509Certificate[] getAcceptedIssuers() { return null; } } OkHttpClient client = new OkHttpClient(); final InetAddress ipAddress = InetAddress.getByName("XX.XXX.XXX.XXX"); // some IP client.setProxy(new Proxy(Proxy.Type.HTTP, new InetSocketAddress(ipAddress, 8888))); SSLContext sslContext = SSLContext.getInstance("TLS"); TrustManager[] trustManagers = new TrustManager[]{new TrustEveryoneManager()}; sslContext.init(null, trustManagers, null); client.setSslSocketFactory(sslContext.getSocketFactory); 

没有请求正在发送出我的应用程序,没有任何例外情况得到logging,所以它似乎在okHttp内默默无闻。 经过进一步的调查,似乎在强制握手的时候,okHttp的Connection.upgradeToTls()中有一个exception被吞噬了。 我给出的exception是: javax.net.ssl.SSLException: SSL handshake terminated: ssl=0x74b522b0: SSL_ERROR_ZERO_RETURN occurred. You should never see this. javax.net.ssl.SSLException: SSL handshake terminated: ssl=0x74b522b0: SSL_ERROR_ZERO_RETURN occurred. You should never see this.

下面的代码产生一个SSLContext ,它在创buildSSLSocketFactory时不会产生任何exception:

 protected SSLContext getTrustingSslContext() throws NoSuchAlgorithmException, KeyStoreException, KeyManagementException { final SSLContextBuilder trustingSSLContextBuilder = SSLContexts.custom() .loadTrustMaterial(null, new TrustStrategy() { @Override public boolean isTrusted(X509Certificate[] chain, String authType) throws CertificateException { return true; // Accepts any ssl cert whether valid or not. } }); return trustingSSLContextBuilder.build(); } 

问题是,我试图完全从我的应用程序中删除所有Apache HttpClient依赖项。 用Apache HttpClient生成SSLContext的底层代码看起来很简单,但我显然错过了一些东西,因为我无法configuration我的SSLContext来匹配它。

任何人都可以产生一个SSLContext实现,而不使用Apache HttpClient,而不是我想要的?

为了防止任何人在这里,这个工作的(唯一的)解决scheme是创buildOkHttpClient就像这里解释的那样。

这里是代码:

 private static OkHttpClient getUnsafeOkHttpClient() { try { // Create a trust manager that does not validate certificate chains final TrustManager[] trustAllCerts = new TrustManager[] { new X509TrustManager() { @Override public void checkClientTrusted(java.security.cert.X509Certificate[] chain, String authType) throws CertificateException { } @Override public void checkServerTrusted(java.security.cert.X509Certificate[] chain, String authType) throws CertificateException { } @Override public java.security.cert.X509Certificate[] getAcceptedIssuers() { return new java.security.cert.X509Certificate[]{}; } } }; // Install the all-trusting trust manager final SSLContext sslContext = SSLContext.getInstance("SSL"); sslContext.init(null, trustAllCerts, new java.security.SecureRandom()); // Create an ssl socket factory with our all-trusting manager final SSLSocketFactory sslSocketFactory = sslContext.getSocketFactory(); OkHttpClient.Builder builder = new OkHttpClient.Builder(); builder.sslSocketFactory(sslSocketFactory, (X509TrustManager)trustAllCerts[0]); builder.hostnameVerifier(new HostnameVerifier() { @Override public boolean verify(String hostname, SSLSession session) { return true; } }); OkHttpClient okHttpClient = builder.build(); return okHttpClient; } catch (Exception e) { throw new RuntimeException(e); } } 

以下方法已被弃用

 sslSocketFactory(SSLSocketFactory sslSocketFactory) 

考虑更新它

 sslSocketFactory(SSLSocketFactory sslSocketFactory, X509TrustManager trustManager) 

更新okhttp3.0,getAcceptedIssuers()函数必须返回一个空数组而不是null

SSLSocketFactory不公开其X509TrustManager,这是OkHttpbuild立一个干净的证书链所需的字段。 此方法反而必须使用reflection来提取信任pipe理器。 应用程序应该更喜欢调用sslSocketFactory(SSLSocketFactory,X509TrustManager),避免这种reflection。

 OkHttpClient.Builder builder = new OkHttpClient.Builder(); builder.sslSocketFactory(sslContext.getSocketFactory(), new X509TrustManager() { @Override public void checkClientTrusted(java.security.cert.X509Certificate[] chain, String authType) throws CertificateException { } @Override public void checkServerTrusted(java.security.cert.X509Certificate[] chain, String authType) throws CertificateException { } @Override public java.security.cert.X509Certificate[] getAcceptedIssuers() { return new java.security.cert.X509Certificate[]{}; } }); 

你永远不应该在代码中重写证书validation! 如果需要进行testing,请使用内部/testingCA并在设备或模拟器上安装CA根证书。 如果您不知道如何设置CA,则可以使用BurpSuite或Charles Proxy。