問題描述:Spring Boot項目中使用RestTemplate調用https接口出現以下錯誤
sun.security.provider.certpath.SunCertPathBuilderException: unable to find valid certification path to requested target
問題原因:Java自帶的安全證書不受信任,在代碼里面的實現方式為在構建restTemplate時忽略證書,繞開SSL驗證,解決代碼如下代碼如下:
import org.springframework.http.client.SimpleClientHttpRequestFactory; import javax.net.ssl.*; import java.io.IOException; import java.net.HttpURLConnection; import java.security.SecureRandom; import java.security.cert.X509Certificate; /** * 跳過證書驗證封裝 */ public class SSL extends SimpleClientHttpRequestFactory { @Override protected void prepareConnection(HttpURLConnection connection, String httpMethod) throws IOException { if (connection instanceof HttpsURLConnection) { prepareHttpsConnection((HttpsURLConnection) connection); } super.prepareConnection(connection, httpMethod); } private void prepareHttpsConnection(HttpsURLConnection connection) { connection.setHostnameVerifier(new SkipHostnameVerifier()); try { connection.setSSLSocketFactory(createSslSocketFactory()); } catch (Exception ex) { // Ignore } } private SSLSocketFactory createSslSocketFactory() throws Exception { SSLContext context = SSLContext.getInstance("TLS"); context.init(null, new TrustManager[] { new SkipX509TrustManager() }, new SecureRandom()); return context.getSocketFactory(); } private class SkipHostnameVerifier implements HostnameVerifier { @Override public boolean verify(String s, SSLSession sslSession) { return true; } } private static class SkipX509TrustManager implements X509TrustManager { @Override public X509Certificate[] getAcceptedIssuers() { return new X509Certificate[0]; } @Override public void checkClientTrusted(X509Certificate[] chain, String authType) { } @Override public void checkServerTrusted(X509Certificate[] chain, String authType) { } } }
@Configuration public class RestTemplateConfig { @Bean public RestTemplate restTemplate(ClientHttpRequestFactory factory) { return new RestTemplate(factory); } @Bean public ClientHttpRequestFactory simpleClientHttpRequestFactory() { SSL factory = new SSL(); factory.setReadTimeout(5000); factory.setConnectTimeout(15000); return factory; } }