遇到了“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();
就这样。
#######
发表评论