背景:服务器A为https的配置环境,服务器B为未配置https的环境,自己的项目部署到服务器B,并且访问服务器A的https接口将出现以下错误:
Caused by: javax.net.ssl.SSLHandshakeException: sun.security.validator.ValidatorException: PKIX path building failed: sun.security.provider.certpath.SunCertPathBuilderException: unable to find valid certification path to requested target
方法一:配置spring boot以信任所有的证书(注:不推荐生产环境)
pom.xml
<!-- https处理 --> <dependency> <groupId>org.apache.httpcomponents</groupId> <artifactId>httpclient</artifactId> <version>4.5.14</version> </dependency>
对于RestTemplate:
HttpComponentsClientHttpRequestFactory clientHttpRequestFactory = new HttpComponentsClientHttpRequestFactory(); SSLContext sslContext = new SSLContextBuilder().loadTrustMaterial(null, (x509Certificates, s) -> true).build(); clientHttpRequestFactory.setHttpClient(HttpClients.custom().setSSLContext(sslContext).build()); RestTemplate restTemplate = new RestTemplate(clientHttpRequestFactory); HttpHeaders httpHeaders = new HttpHeaders(); httpHeaders.setContentType(MediaType.APPLICATION_JSON); if (!targetUrl.endsWith("/")) { targetUrl += "/"; } targetUrl += targetBody + "?" + getParams; HttpEntity<String> formEntity = new HttpEntity<>(null, httpHeaders); ResponseEntity<String> response = restTemplate.exchange(targetUrl, HttpMethod.GET, formEntity, String.class); if (response.getStatusCode() == HttpStatus.OK) { return response.getBody(); } return null;
对于WebClient:(未验证)
import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.web.reactive.function.client.WebClient; import reactor.netty.http.client.HttpClient; import reactor.netty.transport.logging.AdvancedByteBufFormat; import reactor.netty.http.client.HttpClient; import java.security.cert.*; import javax.net.ssl.*; @Configuration public class WebClientConfig { @Bean public WebClient webClient() { TrustManager[] trustAllCerts = new TrustManager[]{new X509TrustManager() { public X509Certificate[] getAcceptedIssuers() { return null; } public void checkClientTrusted(X509Certificate[] certs, String authType) {} public void checkServerTrusted(X509Certificate[] certs, String authType) {} }}; SSLContext sslContext = SSLContextBuilderCustomizer(trustAllCerts).build(); HttpClient httpClient = HttpClient.create().secure(sslSpec -> sslSpec.sslContext(sslContext)); return WebClient.builder().clientConnector(new ReactorClientHttpConnector(httpClient)).build(); } }
对于java.net.URL:
package ****.****.base; import javax.net.ssl.TrustManager; import javax.net.ssl.X509TrustManager; import java.security.cert.X509Certificate; public class TrustAllCerts implements X509TrustManager { @Override public void checkClientTrusted(X509Certificate[] chain, String authType) { // 接受所有客户端证书 } @Override public void checkServerTrusted(X509Certificate[] chain, String authType) { // 接受所有服务器证书 } @Override public X509Certificate[] getAcceptedIssuers() { return new X509Certificate[]{}; } } package ***.***.base; import javax.net.ssl.SSLContext; import javax.net.ssl.SSLSocketFactory; import javax.net.ssl.TrustManager; import java.io.IOException; import java.net.InetAddress; import java.net.Socket; import java.net.UnknownHostException; public class CustomSSLSocketFactory extends SSLSocketFactory { private SSLSocketFactory delegate; public CustomSSLSocketFactory() throws Exception { SSLContext sslContext = SSLContext.getInstance("SSL"); sslContext.init(null, new TrustManager[]{new TrustAllCerts()}, new java.security.SecureRandom()); delegate = sslContext.getSocketFactory(); } @Override public String[] getDefaultCipherSuites() { return delegate.getDefaultCipherSuites(); } @Override public String[] getSupportedCipherSuites() { return delegate.getSupportedCipherSuites(); } @Override public Socket createSocket(Socket s, String host, int port, boolean autoClose) throws IOException { return delegate.createSocket(s, host, port, autoClose); } @Override public Socket createSocket(String host, int port) throws IOException, UnknownHostException { return delegate.createSocket(host, port); } @Override public Socket createSocket(String host, int port, InetAddress localHost, int localPort) throws IOException, UnknownHostException { return delegate.createSocket(host, port, localHost, localPort); } @Override public Socket createSocket(InetAddress host, int port) throws IOException { return delegate.createSocket(host, port); } @Override public Socket createSocket(InetAddress address, int port, InetAddress localAddress, int localPort) throws IOException { return delegate.createSocket(address, port, localAddress, localPort); } } /** * 检测网络资源是否存在/图片是否存在 * */ public boolean checkResourceExists(String webFilePath) { try { /* URL url = new URL(webFilePath); URLConnection uc = url.openConnection(); InputStream in = uc.getInputStream(); if (webFilePath.equalsIgnoreCase(uc.getURL().toString())) { in.close(); } return true; */ URL url = new URL(webFilePath); HttpsURLConnection connection = (HttpsURLConnection) url.openConnection(); connection.setSSLSocketFactory(new CustomSSLSocketFactory()); // 设置自定义的SSL套接字工厂 connection.setRequestMethod("GET"); // 或其他HTTP方法,例如POST等。 具体取决于你的需求。 // 设置其他需要的请求属性,如请求头等。 例如:connection.setRequestProperty("key", "value"); if (connection.getResponseCode()==200) { // 正常流 InputStream responseStream =connection.getInputStream(); }else{ // 错误流 InputStream responseStream =connection.getErrorStream(); } connection.disconnect(); return true; } catch (Exception e) { return false; } }