最近突然后台报错,
I/O error on POST request for "https://test.xxxxxxx.com/api/xxx/xxx/xxx": java.security.cert.CertificateException: No subject alternative DNS name matching test.xxxxxxx.com found.;
这个https://test.xxxxxxx.com/api/xxx/xxx/xxx是我们请求的一个接口,之前一直好好的,突然只要请求就报错。之前能连接得到,怎么就今天就说匹配不到DNS了呢?
我就直接把这个接口单独拿出来用工具,浏览器什么的试一下,发现他们官网也是这个地址,url没错,文档也没错,那问题出在哪呢?
后来发现会不会是我们请求的问题,我们用的是spring自己带的RestTemplate,结果发现实际导致问题产生原因是证书。本来证书这个东西配置,期限实际上就会有些问题,就是可能你一顿操作猛如虎,结果发现证书不行。而且JDK8也开始添加证书的校验,所以说问题会突然冒出来,非常莫名其妙。即使按照它的配置也不一定能成,而且有的测试环境,开发环境什么的压根没有配,或者证书年久失修(很多免费的证书就是一年期限),导致出了问题,很头疼。
解决这个问题,除了说按部就班去配置,也可以直接忽略掉这个证书,毕竟很多接口都有自己的鉴权机制,所以我选择在这方面“偷懒”,跳过证书检测。
我这边是一个已经做好的RestTemplate的配置,就是直接塞一个X509的证书进去
import org.apache.http.conn.ssl.NoopHostnameVerifier;
import org.apache.http.conn.ssl.SSLConnectionSocketFactory;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClientBuilder;
import org.apache.http.impl.client.HttpClients;
import org.apache.http.ssl.SSLContexts;
import org.apache.http.ssl.TrustStrategy;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.http.client.ClientHttpRequestFactory;
import org.springframework.http.client.HttpComponentsClientHttpRequestFactory;
import org.springframework.web.client.RestTemplate;
import javax.net.ssl.SSLContext;
import java.security.KeyManagementException;
import java.security.KeyStoreException;
import java.security.NoSuchAlgorithmException;
/**
* @Author: zp
* @Desc: 忽略证书
*/
@Configuration
public class RestTemplateConfiguration{
@Bean
public RestTemplate restTemplate() {
return new RestTemplate();
}
@Bean
public ClientHttpRequestFactory simpleClientHttpRequestFactory(){
HttpComponentsClientHttpRequestFactory factory = new HttpComponentsClientHttpRequestFactory();
factory.setConnectTimeout(15000);
factory.setReadTimeout(5000);
return factory;
}
public static 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;
}
}
在调用的RestTemplate时,直接这样调用就可以了,忽略掉证书的问题
RestTemplate restTemplate = new RestTemplate(RestTemplateConfiguration.generateHttpRequestFactory());
当然这个问题,主要是知道原因,然后再根据各自的情况来解决,比如说有的公司就是严格重视证书,那你就配置证书,有的不是用的RestTemplate,那就根据对应的代码做更改就可以。