升级Apache HttpClient 5.3至5.4后,信任所有证书配置报错排查
Apache HttpClient 5.4.x 升级后SSL握手异常问题排查与解决
问题根源
你之前使用SSLConnectionSocketFactory时,应该是同时禁用了证书信任校验和主机名验证。但改用ClientTlsStrategyBuilder重构代码后,只配置了信任所有证书,却没显式禁用主机名验证——HttpClient 5.4.x中ClientTlsStrategyBuilder默认会启用严格的主机名校验逻辑,当目标服务器证书的SAN/CN字段和请求域名mms.nw.ru不匹配时,就会抛出CertificateException: No name matching mms.nw.ru found异常。
解决方案
需要在ClientTlsStrategyBuilder中显式配置跳过主机名验证,同时保留信任所有证书的逻辑,完整代码示例如下:
import org.apache.hc.client5.http.impl.io.PoolingHttpClientConnectionManager; import org.apache.hc.client5.http.impl.io.PoolingHttpClientConnectionManagerBuilder; import org.apache.hc.client5.http.impl.nio.PoolingAsyncClientConnectionManager; import org.apache.hc.client5.http.impl.nio.PoolingAsyncClientConnectionManagerBuilder; import org.apache.hc.client5.http.ssl.ClientTlsStrategyBuilder; import org.apache.hc.client5.http.ssl.NoopHostnameVerifier; import org.apache.hc.core5.ssl.SSLContexts; import javax.net.ssl.SSLContext; import javax.net.ssl.TrustManager; import javax.net.ssl.X509TrustManager; import java.security.cert.X509Certificate; // 1. 创建信任所有证书的TrustManager TrustManager[] trustAllCerts = new TrustManager[]{ new X509TrustManager() { @Override public void checkClientTrusted(X509Certificate[] chain, String authType) {} @Override public void checkServerTrusted(X509Certificate[] chain, String authType) {} @Override public X509Certificate[] getAcceptedIssuers() { return new X509Certificate[0]; } } }; // 2. 初始化SSLContext SSLContext sslContext = SSLContext.getInstance("TLS"); sslContext.init(null, trustAllCerts, new java.security.SecureRandom()); // 3. 构建带跳过主机名验证的ClientTlsStrategy ClientTlsStrategy tlsStrategy = ClientTlsStrategyBuilder.create() .setSslContext(sslContext) // 关键:显式禁用主机名验证 .setHostnameVerifier(NoopHostnameVerifier.INSTANCE) .build(); // 4. 配置连接管理器并构建HttpClient PoolingHttpClientConnectionManager connectionManager = PoolingHttpClientConnectionManagerBuilder.create() .setTlsStrategy(tlsStrategy) .build(); CloseableHttpClient httpClient = HttpClients.custom() .setConnectionManager(connectionManager) .build();
注意事项
NoopHostnameVerifier.INSTANCE是HttpClient官方提供的空实现,会完全跳过主机名匹配校验,和你之前使用SSLConnectionSocketFactory的行为一致。- 生产环境强烈不建议禁用证书信任和主机名验证,这会导致请求暴露在中间人攻击风险下,仅建议在测试或内部可信环境中使用。
内容的提问来源于stack exchange,提问作者Beno
相关产品推荐
相关产品推荐

