You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Apache HttpClient HTTPS请求偶现IP访问致证书不匹配,如何强制用DNS?

强制Spring WS(Apache HttpClient)客户端始终使用DNS名称发起HTTPS请求

问题背景

客户端基于Apache HttpClient的Spring WS发起请求时,无规律出现SSL证书匹配错误:

javax.net.ssl.SSLPeerUnverifiedException: Certificate for <g.i.t.n.c.com> doesn't match any of the subject alternative names: [*.t.n.c.com]

原因是客户端偶尔跳过DNS名称直接用IP访问Ingress,导致获取到针对IP的错误证书;正常请求则携带SNI主机名信息,获取匹配g.i.t.n.c.com的正确证书。


解决方案

1. 禁用HttpClient路由缓存

Apache HttpClient默认缓存已解析的路由信息,可能导致后续请求复用IP而非重新解析DNS。通过自定义路由规划器强制每次请求重新解析:

CloseableHttpClient httpClient = HttpClientBuilder.create()
        .setRoutePlanner(new DefaultRoutePlanner(DefaultSchemePortResolver.INSTANCE) {
            @Override
            public HttpRoute determineRoute(HttpHost target, HttpRequest request, HttpContext context) throws HttpException {
                // 清空路由缓存,强制每次重新解析DNS
                context.removeAttribute(HttpClientContext.ROUTE_INFO);
                return super.determineRoute(target, request, context);
            }
        })
        .build();

// 注入到Spring WS的WebServiceTemplate
WebServiceTemplate webServiceTemplate = new WebServiceTemplate();
HttpComponentsMessageSender messageSender = new HttpComponentsMessageSender(httpClient);
webServiceTemplate.setMessageSender(messageSender);

2. 强制SSL连接携带SNI并验证主机名

确保SSL连接工厂始终携带SNI扩展,严格基于DNS名称验证证书:

SSLContext sslContext = SSLContext.getDefault();
SSLConnectionSocketFactory sslSocketFactory = new SSLConnectionSocketFactory(
        sslContext,
        new String[]{"TLSv1.2", "TLSv1.3"},
        null,
        SSLConnectionSocketFactory.getDefaultHostnameVerifier());

CloseableHttpClient httpClient = HttpClientBuilder.create()
        .setSSLSocketFactory(sslSocketFactory)
        // 定期清理闲置连接,避免复用异常路由
        .evictExpiredConnections()
        .evictIdleConnections(30, TimeUnit.SECONDS)
        .build();

3. JVM层面禁用DNS缓存

通过JVM参数强制每次请求重新解析域名,避免缓存IP导致的异常:

-Dsun.net.inetaddr.ttl=0
-Dsun.net.inetaddr.negative.ttl=0
  • sun.net.inetaddr.ttl=0:设置DNS解析结果缓存时间为0,每次请求都重新解析
  • sun.net.inetaddr.negative.ttl=0:设置失败的DNS解析缓存时间为0

4. 检查Spring WS目标URL配置

确保WebServiceTemplate的目标地址始终使用DNS名称,避免代码逻辑中被替换为IP:

webServiceTemplate.setDefaultUri("https://g.i.t.n.c.com/your-service-endpoint");

验证方式

添加JVM参数-Djavax.net.debug=ssl:handshake:verbose,查看ClientHello消息中的SNI扩展,确认请求始终携带正确的DNS名称g.i.t.n.c.com。

内容的提问来源于stack exchange,提问作者Eljah

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.11 13:10:12