1. Foreword
Recently, when interfacing with Tencent conference API interface, it started calling the other party’s interface after authentication. During this process, an error occurred: javax.net.ssl.sslhandshakeexception.
2. Cause of occurrence
When you make an HTTPS request, the trust certificate of the third-party service does not exist in the JDK, resulting in the error javax.net.ssl.sslhandshakeexception: sun.security.validator.validatorexception: PKIX path construction failed.
3. Solution
1. Obtain the root certificate and install the certificate into your JRE’s Java cacerts (install the certificate into the pathoyourjdk/JRE/lib directory/cacerts).
2. Ignore verification of SSL certificates.
In many cases, there is no certificate, so the second scheme is used to ignore the SSL certificate verification in your code.
4. Code
Here, you should distinguish between the way you use to call three-party services (resttemplate, okhttpclient).
1.RestTemplate
package com.hikvision.meeting.config; import org.apache.http.conn.ssl.SSLConnectionSocketFactory; import org.apache.http.conn.ssl.TrustStrategy; import org.apache.http.impl.client.CloseableHttpClient; import org.apache.http.impl.client.HttpClients; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.http.client.HttpComponentsClientHttpRequestFactory; import org.springframework.web.client.RestTemplate; import javax.net.ssl.*; import java.security.cert.CertificateException; import java.security.cert.X509Certificate; /** * @author dongliang7 * @projectName * @ClassName Config2RestTemplate.java * @description: Skip Certificate Validation * @createTime 2021年11月23日 09:59:00 */ @Configuration public class Config2RestTemplate { @Bean public RestTemplate restTemplate() throws Exception { TrustStrategy acceptingTrustStrategy = (X509Certificate[] chain, String authType) -> true; SSLContext sslContext = org.apache.http.ssl.SSLContexts.custom() .loadTrustMaterial(null, acceptingTrustStrategy) .build(); // SSLConnectionSocketFactory csf = new SSLConnectionSocketFactory(sslContext); SSLConnectionSocketFactory csf = new SSLConnectionSocketFactory(createIgnoreVerifySSL(), // Specify the TLS version null, // Specify the algorithm null, // Cancel domain validation new HostnameVerifier() { @Override public boolean verify(String string, SSLSession ssls) { return true; } }); CloseableHttpClient httpClient = HttpClients.custom() .setSSLSocketFactory(csf) .build(); HttpComponentsClientHttpRequestFactory requestFactory = new HttpComponentsClientHttpRequestFactory(); requestFactory.setHttpClient(httpClient); requestFactory.setReadTimeout(60 * 1000);// ms requestFactory.setConnectTimeout(60 * 1000);// ms // The code means whether the request factory class is applied to buffer the request body internal, the default value is true, when the post or put large files will cause memory overflow situation, set to false will flow data directly into the underlying HttpURLConnection requestFactory.setBufferRequestBody(false); RestTemplate restTemplate = new RestTemplate(requestFactory); return restTemplate; } /** * Skip certificate validation sslcontext * * @return * @throws Exception */ private static SSLContext createIgnoreVerifySSL() throws Exception { SSLContext sc = SSLContext.getInstance("TLS"); // Implement an X509TrustManager interface for bypassing authentication without modifying the methods inside X509TrustManager trustManager = new X509TrustManager() { @Override public void checkClientTrusted(X509Certificate[] paramArrayOfX509Certificate, String paramString) throws CertificateException { } @Override public void checkServerTrusted(X509Certificate[] paramArrayOfX509Certificate, String paramString) throws CertificateException { } @Override public X509Certificate[] getAcceptedIssuers() { return null; } }; sc.init(null, new TrustManager[] { trustManager }, null); return sc; } }
2, OkHttpClient
package com.tencent.wemeet.gateway.restapisdk.util; import lombok.extern.slf4j.Slf4j; import okhttp3.OkHttpClient; import javax.net.ssl.*; import java.security.KeyStore; import java.security.NoSuchAlgorithmException; import java.util.Arrays; import java.util.concurrent.TimeUnit; /** * @author dongliang7 * @projectName tenxun-meeting-api * @ClassName SSLSocketClient.java * @description: Create OkHttpClient without SSL (certificate) validation * @createTime 2021年11月19日 09:50:00 */ @Slf4j public class SSLSocketClient { public static OkHttpClient getUnsafeOkHttpClient() { try { // Create a trust manager that does not validate the certificate chain final TrustManager[] trustAllCerts = new TrustManager[]{ new X509TrustManager() { @Override public void checkClientTrusted(java.security.cert.X509Certificate[] chain, String authType) {} @Override public void checkServerTrusted(java.security.cert.X509Certificate[] chain, String authType) {} @Override public java.security.cert.X509Certificate[] getAcceptedIssuers() { return new java.security.cert.X509Certificate[]{}; } } }; if (trustAllCerts.length != 1 || !(trustAllCerts[0] instanceof X509TrustManager)) { throw new IllegalStateException("Unexpected default trust managers:" + Arrays.toString(trustAllCerts)); } X509TrustManager x509TrustManager = (X509TrustManager) trustAllCerts[0]; // Install the full trust trust manager final SSLContext sslContext = SSLContext.getInstance("SSL"); sslContext.init(null, trustAllCerts, new java.security.SecureRandom()); // Create the ssl socket factory using our fully trusted manager final SSLSocketFactory sslSocketFactory = sslContext.getSocketFactory(); OkHttpClient.Builder builder = new OkHttpClient.Builder() .connectTimeout(60 , TimeUnit.SECONDS).readTimeout(60 , TimeUnit.SECONDS).writeTimeout(120 , TimeUnit.SECONDS); builder.sslSocketFactory(sslSocketFactory , x509TrustManager); builder.hostnameVerifier(new HostnameVerifier() { @Override public boolean verify(String hostname, SSLSession session) { return true; } }); OkHttpClient okHttpClient = builder.build(); return okHttpClient; } catch (Exception e) { log.error("Failed to create OkHttpClient without SSL (certificate) validation: {}", e.getMessage()); throw new RuntimeException(e); } } }
Get okhttpclient:
// Create OkHttpClient without SSL (certificate) authentication private static final OkHttpClient okHttpClient = SSLSocketClient.getUnsafeOkHttpClient();