HTTP Client CFCA SSL证书授信问题处理

目录

HTTP Client CFCA SSL证书授信问题处理

问题描述

调研

解决方案

方案1: 将根证书或当前证书导入到JDK的授信库

方案2: HTTP Client 忽略所有SSL证书的验证

方案3: HTTP Client 只忽略CFCA签发的SSL证书的验证


HTTP Client CFCA SSL证书授信问题处理

问题描述

通过HTTP Client 访问CFCA 签发的SSL证书的域名时出错,异常信息:

javax.net.ssl.SSLHandshakeException: sun.security.validator.ValidatorException: PKIX path building failed: sun.security.provider.certpath.SunCertPathBuilderException: unable to find valid certification path to requested target
    at java.base/sun.security.ssl.Alerts.getSSLException(Alerts.java:198)
    at java.base/sun.security.ssl.SSLSocketImpl.fatal(SSLSocketImpl.java:1969)
    at java.base/sun.security.ssl.Handshaker.fatalSE(Handshaker.java:345)
    at java.base/sun.security.ssl.Handshaker.fatalSE(Handshaker.java:339)
    at java.base/sun.security.ssl.ClientHandshaker.checkServerCerts(ClientHandshaker.java:1968)
    at java.base/sun.security.ssl.ClientHandshaker.serverCertificate(ClientHandshaker.java:1777)
    at java.base/sun.security.ssl.ClientHandshaker.processMessage(ClientHandshaker.java:264)
    at java.base/sun.security.ssl.Handshaker.processLoop(Handshaker.java:1092)
    at java.base/sun.security.ssl.Handshaker.processRecord(Handshaker.java:1026)
    at java.base/sun.security.ssl.SSLSocketImpl.processInputRecord(SSLSocketImpl.java:1137)
    at java.base/sun.security.ssl.SSLSocketImpl.readRecord(SSLSocketImpl.java:1074)
    at java.base/sun.security.ssl.SSLSocketImpl.readRecord(SSLSocketImpl.java:973)
    at java.base/sun.security.ssl.SSLSocketImpl.performInitialHandshake(SSLSocketImpl.java:1402)
    at java.base/sun.security.ssl.SSLSocketImpl.startHandshake(SSLSocketImpl.java:1429)
    at java.base/sun.security.ssl.SSLSocketImpl.startHandshake(SSLSocketImpl.java:1413)
    at org.apache.http.conn.ssl.SSLConnectionSocketFactory.createLayeredSocket(SSLConnectionSocketFactory.java:396)
    at org.apache.http.conn.ssl.SSLConnectionSocketFactory.connectSocket(SSLConnectionSocketFactory.java:355)
    at org.apache.http.impl.conn.DefaultHttpClientConnectionOperator.connect(DefaultHttpClientConnectionOperator.java:142)
    at org.apache.http.impl.conn.PoolingHttpClientConnectionManager.connect(PoolingHttpClientConnectionManager.java:373)
    at org.apache.http.impl.execchain.MainClientExec.establishRoute(MainClientExec.java:381)
    at org.apache.http.impl.execchain.MainClientExec.execute(MainClientExec.java:237)
    at org.apache.http.impl.execchain.ProtocolExec.execute(ProtocolExec.java:185)
    at org.apache.http.impl.execchain.RetryExec.execute(RetryExec.java:89)
    at org.apache.http.impl.execchain.RedirectExec.execute(RedirectExec.java:111)
    at org.apache.http.impl.client.InternalHttpClient.doExecute(InternalHttpClient.java:185)
    at org.apache.http.impl.client.CloseableHttpClient.execute(CloseableHttpClient.java:83)
    at org.apache.http.impl.client.CloseableHttpClient.execute(CloseableHttpClient.java:108)

证书信息:

调研

因为JDK 没有把CFCA的根证书加入的授信的库列表里,但市面上主流的浏览器基本都加入,因此导致浏览器可以正常方法,但通过HTTP Client 访问就会提示SSL证书检查不通过。

解决方案

方案1: 将根证书或当前证书导入到JDK的授信库

该方案实现难度较大,需要在所有代码执行的地方都执行导入的动作

方案2: HTTP Client 忽略所有SSL证书的验证

构建一个信任所有证书的SSLContext

public static SSLContext getSSLIgnoreContext(){
    try {
        return SSLContexts.custom().loadTrustMaterial(new TrustAllStrategy()).build();
    } catch (NoSuchAlgorithmException e) {
        log.warn(e);
    } catch (KeyManagementException e) {
        log.warn(e);
    } catch (KeyStoreException e) {
        log.warn(e);
    }
    return null;
}

创建HTTP Client,指定SSLContext

public static CloseableHttpClient getSSLIgnoreCheckHttpClient(){
    return HttpClientBuilder.create()
        .setSSLContext(getSSLIgnoreContext())
        .build();
}
该方案的风险较大,会导致所有SSL证书都不验证。

方案3: HTTP Client 只忽略CFCA签发的SSL证书的验证

创建一个CFCA免验证的授信策略类TrustStrategy

public class CFCATrustStrategy implements TrustStrategy {

    /**
     * Determines whether the certificate chain can be trusted without consulting the trust manager
     * configured in the actual SSL context. This method can be used to override the standard JSSE
     * certificate verification process.
     * <p>
     * Please note that, if this method returns {@code false}, the trust manager configured
     * in the actual SSL context can still clear the certificate as trusted.
     *
     * @param chain    the peer certificate chain
     * @param authType the authentication type based on the client certificate
     * @return {@code true} if the certificate can be trusted without verification by
     * the trust manager, {@code false} otherwise.
     * @throws CertificateException thrown if the certificate is not trusted or invalid.
     */
    @Override public boolean isTrusted(X509Certificate[] chain, String authType) throws CertificateException {
        if(chain!=null && chain.length > 0){
            for(X509Certificate certificate:chain){
                if("CN=CFCA EV ROOT, O=China Financial Certification Authority, C=CN".equals(certificate.getSubjectDN().getName())){
                    return true;
                }
            }
        }
        return false;
    }
}

构建一个只忽略CFCA签发的证书的SSLContext

public static SSLContext getCFCASSLIgnoreContext(){
    try {
        return SSLContexts.custom().loadTrustMaterial(new CFCATrustStrategy()).build();
    } catch (NoSuchAlgorithmException e) {
        log.warn(e);
    } catch (KeyManagementException e) {
        log.warn(e);
    } catch (KeyStoreException e) {
        log.warn(e);
    }
    return null;
}

创建HTTP Client,指定SSLContext

public static CloseableHttpClient getSSLIgnoreCheckHttpClient(){
    return HttpClientBuilder.create()
        .setSSLContext(getSSLIgnoreContext())
        .build();
}
该方案的风险较小,推荐使用。
  • 1
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值