1. 概述

在这个教程中,我们将学习如何创建并配置一个OkHttpClient以信任所有证书。有关OkHttp的更多详细信息,请参阅我们的相关文章

2. Maven依赖

首先,让我们在pom.xml文件中添加OkHttp的依赖:

<dependency>
    <groupId>com.squareup.okhttp3</groupId>
    <artifactId>okhttp</artifactId>
    <version>5.0.0-alpha.12</version>
</dependency>

3. 使用标准的OkHttpClient

首先,我们使用一个标准的OkHttpClient对象,尝试调用一个证书已过期的网页:

OkHttpClient client = new OkHttpClient.Builder().build();
client.newCall(new Request.Builder().url("https://expired.badssl.com/").build()).execute();

输出堆栈跟踪如下:

sun.security.validator.ValidatorException: PKIX path validation failed: java.security.cert.CertPathValidatorException: validity check failed

现在,当我们尝试另一个使用自签名证书的网站时,会看到错误:

sun.security.validator.ValidatorException: PKIX path building failed: sun.security.provider.certpath.SunCertPathBuilderException: unable to find valid certification path to requested target

接着,尝试一个证书与主机名不匹配的网站:

Hostname wrong.host.badssl.com not verified

如你所见,默认情况下,OkHttpClient会在调用证书有问题的网站时抛出错误。接下来,我们将学习如何创建并配置一个OkHttpClient来信任所有证书。

4. 设置OkHttpClient信任所有证书

让我们创建一个包含单个X509TrustManager的TrustManager数组,这个X509TrustManager通过重写其方法来禁用默认的证书验证

TrustManager[] trustAllCerts = new TrustManager[]{
    new X509TrustManager() {
        @Override
        public void checkClientTrusted(java.security.cert.X509Certificate[] chain, String authType) {
        }

        @Override
        public void checkServerTrusted(java.security.cert.X509Certificate[] chain, String authType) {
        }

        @Override
        public java.security.cert.X509Certificate[] getAcceptedIssuers() {
            return new java.security.cert.X509Certificate[]{};
        }
    }
};

我们将使用这个TrustManager数组来创建一个SSLContext

SSLContext sslContext = SSLContext.getInstance("SSL");
sslContext.init(null, trustAllCerts, new java.security.SecureRandom());

然后,我们将使用这个SSLContext设置OkHttpClient构建器的SSLSocketFactory:

OkHttpClient.Builder newBuilder = new OkHttpClient.Builder();
newBuilder.sslSocketFactory(sslContext.getSocketFactory(), (X509TrustManager) trustAllCerts[0]);
newBuilder.hostnameVerifier((hostname, session) -> true);

我们还将新构建器的HostnameVerifier设置为一个新的HostnameVerifier对象,其验证方法始终返回true。

最后,我们可以获取一个新的OkHttpClient对象,再次调用有问题的证书的网站,而不会出现任何错误:

OkHttpClient newClient = newBuilder.build();
newClient.newCall(new Request.Builder().url("https://expired.badssl.com/").build()).execute();

5. 总结

在这篇简短的文章中,我们了解了如何创建并配置一个OkHttpClient以信任所有证书。当然,信任所有证书并不建议,但在某些特殊情况下可能会需要。本文的完整代码可在GitHub上找到