解决PKIX:unable to find valid certification path to requested target

遇到了“unable to find valid certification path to requested target”这样的问题。

错误详情如下:

at sun.security.ssl.SSLSocketImpl.startHandshake(SSLSocketImpl.java:1391)
        at org.apache.http.impl.execchain.RedirectExec.execute(RedirectExec.java:111)
        at java.util.concurrent.Executors$RunnableAdapter.call(Executors.java:511)
        at java.util.concurrent.FutureTask.run(FutureTask.java:266)
        at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1142)
        at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:617)
        at java.lang.Thread.run(Thread.java:745)
Caused by: sun.security.validator.ValidatorException: PKIX path building failed: sun.security.provider.certpath.SunCertPathBuilderException: unable to find valid certification path to requested target
        at sun.security.validator.PKIXValidator.doBuild(PKIXValidator.java:387)
        at sun.security.validator.PKIXValidator.engineValidate(PKIXValidator.java:292)
        at sun.security.validator.Validator.validate(Validator.java:260)
        at sun.security.ssl.X509TrustManagerImpl.validate(X509TrustManagerImpl.java:324)
        at sun.security.ssl.X509TrustManagerImpl.checkTrusted(X509TrustManagerImpl.java:229)
        at sun.security.ssl.X509TrustManagerImpl.checkServerTrusted(X509TrustManagerImpl.java:124)
        at sun.security.ssl.ClientHandshaker.serverCertificate(ClientHandshaker.java:1460)
        ... 35 common frames omitted
Caused by: sun.security.provider.certpath.SunCertPathBuilderException: unable to find valid certification path to requested target
        at sun.security.provider.certpath.SunCertPathBuilder.build(SunCertPathBuilder.java:145)
        at sun.security.provider.certpath.SunCertPathBuilder.engineBuild(SunCertPathBuilder.java:131)
        at java.security.cert.CertPathBuilder.build(CertPathBuilder.java:280)
        at sun.security.validator.PKIXValidator.doBuild(PKIXValidator.java:382)
        ... 41 common frames omitted

从异常信息中可以看到错误是因为找不到证书导致的。

解决方案有两个。

正常的方案当然是找到证书并安装证书。这种方案能找到一大把,在这里不做展开。

说个暴力的方案:取消证书认证,信任所有请求链接。

使用的工具是fluent-http-client,maven地址是:

        <dependency>
            <groupId>org.apache.httpcomponents</groupId>
            <artifactId>fluent-hc</artifactId>
            <version>4.5.4</version>
        </dependency>

首先创建一个自定义的HttpClient实例。这个实例将信任所有的请求链接。实例详情如下:

    final static PoolingHttpClientConnectionManager CONN_MGR;
    final static org.apache.http.client.HttpClient CLIENT;

    static {
        SSLConnectionSocketFactory sf = null;

        try {
            //信任所有
            SSLContext sslc = new SSLContextBuilder().loadTrustMaterial(null, (chain, authType) -> true).build();
            sf = new SSLConnectionSocketFactory(sslc);
        } catch (Exception e) {
            logger.error("Create socket factory failed.", e);
        }


        final Registry<ConnectionSocketFactory> sfr = RegistryBuilder.<ConnectionSocketFactory>create()
                .register("http", PlainConnectionSocketFactory.getSocketFactory())
                .register("https", null != sf ? sf : SSLConnectionSocketFactory.getSocketFactory())
                .build();

        CONN_MGR = new PoolingHttpClientConnectionManager(sfr);
        CONN_MGR.setDefaultMaxPerRoute(1024);
        CONN_MGR.setMaxTotal(512);
        CONN_MGR.setValidateAfterInactivity(1000);

        CLIENT = HttpClientBuilder.create()
                // 这里主要用来避免使用http链接请求实际为https的地址
                .setSSLSocketFactory(sf)
                .setConnectionManager(CONN_MGR)
                .build();
    }

注意代码中的两处注释,是关键。

然后绑定新创建的实例,执行一个Get请求:

Executor.newInstance(CLIENT).execute(Request.Get("http://www.json.cn?a=b")).returnResponse();

就这样。

#######

发表评论

这个站点使用 Akismet 来减少垃圾评论。了解你的评论数据如何被处理