我们正在进行一个项目,该项目通过Socket
连接到外部服务器,连接类型为ssl
。证书是自签名的,项目代码将System Property
设置为通过以下方式通过证书验证:
System.setProperty("javax.net.ssl.trustStorePassword", .....);
System.setProperty("javax.net.ssl.trustStore", ....);
我们正在尝试扩展该项目并使用Spring RestTemplate
。但是发生了一些奇怪的事情!
当我们创建并注入一个新的RestTemplate
对象时,旧的代码停止工作,我得到了unable to find valid certification path to requested target
代码既没有共同点,也没有源代码,对象中也没有。。。
发生了什么?Spring RestTemplate
是否会更改或影响系统属性?
我发现默认的ApacheHttpComponent
会导致错误。我不知道为什么!!
我换成了OKHttp3
。旧的密码又开始工作了。
这是一个示例代码:
由于它是自签名证书,我将它们从商店添加到OkkHttpHandshakeCertificates
List<X509Certificate> certificates = getCertificatesFromTrustStore();
Builder certificateBuilder = new HandshakeCertificates.Builder();
for (X509Certificate x509Certificate : certificates) {
certificateBuilder.addTrustedCertificate(x509Certificate);
}
HandshakeCertificates handshakeCertificates = certificateBuilder.build();
ConnectionPool okHttpConnectionPool = new ConnectionPool(MAX_IDLE_CONNETION, KEEP_ALIVE_DURATION, TimeUnit.SECONDS);
OkHttpClient okHttpClient = new OkHttpClient.Builder()
.hostnameVerifier(new NoopHostnameVerifier())
.retryOnConnectionFailure(false)
.connectTimeout(CONNECT_TIMEOUT, TimeUnit.SECONDS)
.sslSocketFactory(handshakeCertificates.sslSocketFactory(), handshakeCertificates.trustManager())
.connectionPool(okHttpConnectionPool)
.build();
ClientHttpRequestFactory clientHttpRequestFactory = new OkHttp3ClientHttpRequestFactory(okHttpClient);
RestTemplate restTemplate = new RestTemplate(
new BufferingClientHttpRequestFactory(
clientHttpRequestFactory
));
//Set error handler
MyRestTemplateResponseErrorHandler errorHandler = new MyRestTemplateResponseErrorHandler();
errorHandler.setMessageConverters(restTemplate.getMessageConverters());
restTemplate.setErrorHandler(errorHandler);
return restTemplate;
}
private List<X509Certificate> getCertificatesFromTrustStore() throws KeyStoreException, IOException,
NoSuchAlgorithmException, CertificateException, FileNotFoundException, InvalidAlgorithmParameterException {
KeyStore truststore = KeyStore.getInstance("JKS");
truststore.load(new FileInputStream(trustStorePath), keystorePass.toCharArray());
Set<TrustAnchor> trustAnchors = new PKIXParameters(truststore).getTrustAnchors();
LOG.debug("{} certificates found in {} which will be used", trustAnchors.size(), trustStorePath);
List<X509Certificate> certificates = trustAnchors.stream()
.map(TrustAnchor::getTrustedCert)
.collect(Collectors.toList());
return certificates;
}