遇到了“unable to find valid certification path to requested target”这样的问题。
错误详情如下:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 |
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地址是:
1 2 3 4 5 |
<dependency> <groupId>org.apache.httpcomponents</groupId> <artifactId>fluent-hc</artifactId> <version>4.5.4</version> </dependency> |
首先创建一个自定义的HttpClient实例。这个实例将信任所有的请求链接。实例详情如下:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 |
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请求:
1 |
Executor.newInstance(CLIENT).execute(Request.Get("http://www.json.cn?a=b")).returnResponse(); |
就这样。
#######
发表评论