jdk11 httpclient 忽略域名校验(hostname校验)配置方法及源码探究

文章探讨了在使用JDK11的Httpclient时如何实现证书双向认证但忽略域名校验的问题,虽然尝试通过SSLParameters设置,但因内部类限制,最终解决方案是在系统属性中设置`jdk.internal.httpclient.disableHostnameVerification`。
摘要由CSDN通过智能技术生成

最近在使用JDK11及以后支持的Httpclient,需求是需要证书双向认证,但是要忽略域名的校验,以前用apache httpclient的时候有一个DefaultHostnameVerifier可以会忽略域名校验,但是jdk自带的httpclient并没有支持此功能。

一句话解决方案:

代码配置

final Properties props = System.getProperties();
props.setProperty("jdk.internal.httpclient.disableHostnameVerification", Boolean.TRUE.toString());

或者启动参数配置

 -Djdk.internal.httpclient.disableHostnameVerification

下面是源码探究。

在使用httpclient时,会发现它支持配置SslParams, SSLParameters是SSLEngine使用的,如果SSLParametersidentificationAlgorithm属性为空,SSLEngine就会跳过校验域名,代码在:
sun.security.ssl.X509TrustManagerImpl的288行,代码如下:

 // check endpoint identity
            String identityAlg = engine.getSSLParameters().
                    getEndpointIdentificationAlgorithm();
// 发现为空就跳过域名的校验
            if (identityAlg != null && !identityAlg.isEmpty()) {
                checkIdentity(session, trustedChain,
                        identityAlg, checkClientTrusted);
            }

那么我们是不是就可以配置httpclient的SSLParameters,直接达成目标呢?

        SSLParameters parameters = new SSLParameters();
        parameters.setEndpointIdentificationAlgorithm("");
        var httpClient = HttpClient.newBuilder()
                ...
                .sslParameters(parameters)
                .build();

看起来我们是配置成功了,但是实际使用时仍然会发现该配置无效,原因是这个配置项被Httpclient丢弃了,在jdk.internal.net.http.AbstractAsyncSSLConnectioncreateSSLParameters(HttpClientImpl client, ServerName serverName,String[] alpn)方法,可以看到用于创建SSLEngine的SSLParameters被创建的过程:

private static SSLParameters createSSLParameters(HttpClientImpl client,
                                                     ServerName serverName,
                                                     String[] alpn) {
        SSLParameters sslp = client.sslParameters();
        // 复制了一份 SSLParameters
        SSLParameters sslParameters = Utils.copySSLParameters(sslp);
        // 其他配置内容

        // 重点: disableHostnameVerification 这个变量会导致我们配置的IdentificationAlgorithm被覆盖!
        if (!disableHostnameVerification)
            sslParameters.setEndpointIdentificationAlgorithm("HTTPS");
       
        return sslParameters;
    }

在代码中可以发现,AbstractAsyncSSLConnection的disableHostnameVerification属性会导致我们配置的sslParams.identificationAlgorithm被覆盖,从而导致配置无效。

继续跟下去,disableHostnameVerificationjdk.internal.net.http.common.Utils.isHostnameVerificationDisabled属性,而类 jdk.internal.net.http.common.Utils是httpclient的内部类,未对外开放,所以我们无法在外部修改。通过阅读java.net.httpmodule-info.java,里面有说明可以修改此变量:

jdk.internal.httpclient.disableHostnameVerification (default: false) 
If true (or set to an empty string), hostname verification in SSL certificates is disabled. This is a system property only and not available in conf/ net. properties. It is provided for testing purposes only.

由此,真相大白,这项配置必须在system property中配置。

  • 5
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值