Spring Boot RestTemplate请求证书问题
场景
GG!忙活了一个月的需求正式上线,第一天就嗷嗷报错,没一条数据是请求成功的。因为程序里插入了监控程序,监控程序报错,毕竟这个项目刚开始引入都是后台处理,不添加监控程序真报错谁也不知道。如果查过10次报错就会发送提示邮件,告诉我们大面积报错了,赶紧处理。大清早的领导就哐哐@我们。程序报错邮件发了,赶紧去看!
报错描述
java
org.springframework.web.client.ResourceAccessException:
I/O error on POST request for "https://xxxxx.com": PKIX path building failed: sun.security.provider.certpath.SunCertPathBuilderException: unable to find valid certification path to requested target; nested exception is javax.net.ssl.SSLHandshakeException: PKIX path building failed:
原因
由于该网站的SSL证书不受信,所以才会报这个错误。但是测试环境好的,很头秃!
解决
其实有三种解决方案:
- 信任所有证书:本次是这么解决的,由于是内网走代理,请求的
url
固定。
java
@Bean
public RestTemplate restTemplate() throws NoSuchAlgorithmException, KeyStoreException, KeyManagementException {
return new RestTemplate(generateHttpRequestFactory());
}
private HttpComponentsClientHttpRequestFactory generateHttpRequestFactory()
throws NoSuchAlgorithmException, KeyManagementException, KeyStoreException
{
TrustStrategy acceptingTrustStrategy = (x509Certificates, authType) -> true;
SSLContext sslContext = SSLContexts.custom().loadTrustMaterial(null, acceptingTrustStrategy).build();
SSLConnectionSocketFactory connectionSocketFactory = new SSLConnectionSocketFactory(sslContext, new NoopHostnameVerifier());
HttpClientBuilder httpClientBuilder = HttpClients.custom();
httpClientBuilder.setSSLSocketFactory(connectionSocketFactory);
CloseableHttpClient httpClient = httpClientBuilder.build();
HttpComponentsClientHttpRequestFactory factory = new HttpComponentsClientHttpRequestFactory();
factory.setHttpClient(httpClient);
return factory;
}
有可能你引入的包找不到相对应的依赖,需要引入apache
的请求包:
java
implementation 'org.apache.httpcomponents:httpclient:4.5.1'
- 将不信任的证书加入到JVM默认信任证书
- 单独为不信任的网站生成证书并在项目中指定
后面这两种比较类似,都需要使用
keytool
工具,但是对此项目来讲不是很合适,所以目前只使用第一种。其他两种后面用到了再具体补充。
补充
之前也遇到一个报错也是这么解决的
I/O error on POST request for "https://xxxx.com": java.security.cert.CertificateException: No subject alternative DNS name matching test.xxxxxxx.com found.;
记录一下