背景:生产环境调用三方SDK所有请求提示异常
本地环境复现日志如下:
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
at sun.security.ssl.Alerts.getSSLException(Alerts.java:192)
at sun.security.ssl.SSLSocketImpl.fatal(SSLSocketImpl.java:1949)
at sun.security.ssl.Handshaker.fatalSE(Handshaker.java:302)
at sun.security.ssl.Handshaker.fatalSE(Handshaker.java:296)
at sun.security.ssl.ClientHandshaker.serverCertificate(ClientHandshaker.java:1506)
at sun.security.ssl.ClientHandshaker.processMessage(ClientHandshaker.java:216)
at sun.security.ssl.Handshaker.processLoop(Handshaker.java:979)
at sun.security.ssl.Handshaker.process_record(Handshaker.java:914)
at sun.security.ssl.SSLSocketImpl.readRecord(SSLSocketImpl.java:1062)
at sun.security.ssl.SSLSocketImpl.performInitialHandshake(SSLSocketImpl.java:1375)
at sun.security.ssl.SSLSocketImpl.startHandshake(SSLSocketImpl.java:1403)
at sun.security.ssl.SSLSocketImpl.startHandshake(SSLSocketImpl.java:1387)
at okhttp3.internal.connection.RealConnection.connectTls(RealConnection.kt:350)
at okhttp3.internal.connection.RealConnection.establishProtocol(RealConnection.kt:308)
at okhttp3.internal.connection.RealConnection.connect(RealConnection.kt:182)
at okhttp3.internal.connection.ExchangeFinder.findConnection(ExchangeFinder.kt:238)
at okhttp3.internal.connection.ExchangeFinder.findHealthyConnection(ExchangeFinder.kt:111)
at okhttp3.internal.connection.ExchangeFinder.find(ExchangeFinder.kt:79)
at okhttp3.internal.connection.Transmitter.newExchange$okhttp(Transmitter.kt:163)
at okhttp3.internal.connection.ConnectInterceptor.intercept(ConnectInterceptor.kt:35)
at okhttp3.internal.http.RealInterceptorChain.proceed(RealInterceptorChain.kt:112)
at okhttp3.internal.http.RealInterceptorChain.proceed(RealInterceptorChain.kt:87)
at okhttp3.internal.cache.CacheInterceptor.intercept(CacheInterceptor.kt:82)
at okhttp3.internal.http.RealInterceptorChain.proceed(RealInterceptorChain.kt:112)
at okhttp3.internal.http.RealInterceptorChain.proceed(RealInterceptorChain.kt:87)
at okhttp3.internal.http.BridgeInterceptor.intercept(BridgeInterceptor.kt:84)
at okhttp3.internal.http.RealInterceptorChain.proceed(RealInterceptorChain.kt:112)
at okhttp3.internal.http.RetryAndFollowUpInterceptor.intercept(RetryAndFollowUpInterceptor.kt:71)
at okhttp3.internal.http.RealInterceptorChain.proceed(RealInterceptorChain.kt:112)
at okhttp3.internal.http.RealInterceptorChain.proceed(RealInterceptorChain.kt:87)
at okhttp3.RealCall.getResponseWithInterceptorChain(RealCall.kt:194)
at okhttp3.RealCall.execute(RealCall.kt:67)
at com.xiaohongshu.fls.opensdk.client.OrderClient.execute(OrderClient.java:35)
at com.ewp.datacenter.module.xiaohongshu.service.RedBookServiceImpl.main(RedBookServiceImpl.java:459)
Caused by: sun.security.validator.ValidatorException: PKIX path building failed: sun.security.provider.certpath.SunCertPathBuilderException: unable to find valid certification path to requested target
at sun.security.validator.PKIXValidator.doBuild(PKIXValidator.java:387)
at sun.security.validator.PKIXValidator.engineValidate(PKIXValidator.java:292)
at sun.security.validator.Validator.validate(Validator.java:260)
at sun.security.ssl.X509TrustManagerImpl.validate(X509TrustManagerImpl.java:324)
at sun.security.ssl.X509TrustManagerImpl.checkTrusted(X509TrustManagerImpl.java:229)
at sun.security.ssl.X509TrustManagerImpl.checkServerTrusted(X509TrustManagerImpl.java:124)
at sun.security.ssl.ClientHandshaker.serverCertificate(ClientHandshaker.java:1488)
... 29 common frames omitted
Caused by: sun.security.provider.certpath.SunCertPathBuilderException: unable to find valid certification path to requested target
at sun.security.provider.certpath.SunCertPathBuilder.build(SunCertPathBuilder.java:146)
at sun.security.provider.certpath.SunCertPathBuilder.engineBuild(SunCertPathBuilder.java:131)
at java.security.cert.CertPathBuilder.build(CertPathBuilder.java:280)
at sun.security.validator.PKIXValidator.doBuild(PKIXValidator.java:382)
... 35 common frames omitted
本地复现环境:
// 本地系统
版本 Windows 11 专业版
版本号 24H2
// JDK版本(子版本严格限制)
java version "1.8.0_60"
Java(TM) SE Runtime Environment (build 1.8.0_60-b27)
Java HotSpot(TM) 64-Bit Server VM (build 25.60-b23, mixed mode)
// pom依赖
<dependency>
<groupId>com.squareup.okhttp3</groupId>
<artifactId>okhttp</artifactId>
<version>4.3.1</version>
</dependency>
本地复现代码:
注意:代码块A和代码块B只能放开一个,另一个需要注释
代码块A为复现问题代码块
代码块B为下下策:关闭ssl证书验证
package edu.xq.test;
import java.io.IOException;
import java.security.KeyManagementException;
import java.security.NoSuchAlgorithmException;
import java.util.concurrent.TimeUnit;
import javax.net.ssl.SSLContext;
import javax.net.ssl.TrustManager;
import javax.net.ssl.X509TrustManager;
import okhttp3.MediaType;
import okhttp3.OkHttpClient;
import okhttp3.Request;
import okhttp3.RequestBody;
import okhttp3.Response;
public class OKHttpTest {
public static final OkHttpClient okHttpClient;
/**
* 代码块A:创建一个默认的OkHttpClient实例
*/
static {
okHttpClient = (new OkHttpClient.Builder())
.readTimeout(30L, TimeUnit.SECONDS)
.writeTimeout(30L, TimeUnit.SECONDS)
.connectTimeout(5L, TimeUnit.SECONDS)
.retryOnConnectionFailure(true).build();
}
/**
* 代码块B:创建一个信任所有证书的OkHttpClient实例(PS:AI工具写代码确实好用)
*/
// static {
// // 创建信任所有证书的TrustManager
// 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[]{}; }
// }
// };
//
// try {
// SSLContext sslContext = SSLContext.getInstance("SSL");
// sslContext.init(null, trustAllCerts, new java.security.SecureRandom());
//
// okHttpClient = new OkHttpClient.Builder()
// .sslSocketFactory(sslContext.getSocketFactory(), (X509TrustManager)trustAllCerts[0])
// .hostnameVerifier((hostname, session) -> true)
// .readTimeout(30L, TimeUnit.SECONDS)
// .writeTimeout(30L, TimeUnit.SECONDS)
// .connectTimeout(5L, TimeUnit.SECONDS)
// .retryOnConnectionFailure(true)
// .build();
// } catch (NoSuchAlgorithmException | KeyManagementException e) {
// throw new RuntimeException("Failed to create unsafe SSL context", e);
// }
// }
public static void main(String[] args) throws Exception {
RequestBody body = RequestBody.create(MediaType.parse("application/json; charset=utf-8"), "{}");
Request httpRequest = (new Request.Builder()).url("https://ark.xiaohongshu.com/ark/open_api/v3/common_controller").post(body).build();
Response openapiResponse = null;
try {
openapiResponse = okHttpClient.newCall(httpRequest).execute();
} catch (IOException e) {
throw new RuntimeException(e);
}
String responseBody = openapiResponse.body().string();
System.out.println(responseBody);
}
}
问题描述:
OkHttp调用JRE的SSL证书校验不通过
处理思路:
1、服务端看:那就看该网站的SSL证书配置是否正常,搜索分析问题发现有人提到
1.1 证书是由 非受信任的根证书颁发机构 颁发的;eg:自己生成etc.
1.2 证书链的问题:服务端重新校验配置;
2、客户端看:那就看谁在校验,取消校验或者升级对于加密库
2.1 JRE版本低,里面的证书库教旧:升级JRE加密库或JDK版本
2.2 取消校验:生产不推荐哦
解决方案:
本测试样本已经排除服务端问题,故提供客户端处理方案
方案一:校验不通过,那就不校验,放开校验
参考 本地复现代码 注释代码块A 放开代码块B
方案二:替换依赖SDK中的class(其实也是方案一)
因为不是自己代码,So自己本地反编译好,替换SDK中的class即可。(操作同方法一)
方案三:升级jdk子版本(其他中间子版本没测试,原来本机就是这个版本切换就好了)
java version "1.8.0_202"
Java(TM) SE Runtime Environment (build 1.8.0_202-b08)
Java HotSpot(TM) 64-Bit Server VM (build 25.202-b08, mixed mode)
方案四:将证书放到本地,毕竟不是长久之计,测试学习或临时处理吧
1、将 目标网站的
crt
证书[目标网站的crt
证书在本机的路径]导入到 Java 的默认证书库cacerts
中,并给该证书指定了别名 [证书别名]。这使得 Java 在运行时可以信任该证书所代表的实体或服务器,常用于 SSL/TLS 连接等场景。(红字替换成自己的,keytool记得用jre的[jdk下好像也有个同名工具,记得区分]。j)keytool -import -v -trustcacerts -alias [证书别名] -file [目标网站的
crt
证书在本机的路径] -storepass changeit -keystore %JAVA_HOME%/jre/lib/security/cacerts2、使用
keytool
工具,查询列出位于%JAVA_HOME%\jre\lib\security\cacerts
的密钥库中的所有证书信息:keytool -list -keystore %JAVA_HOME%\jre\lib\security\cacerts -storepass changeit
总结:
综上所述,推荐对方案三进行实施,即升级到JDK更高的子版本。如果仍然遇到问题,可以考虑结合方案四,将相关证书导入到信任库中。同时,建议在生产环境中严格遵循SSL证书验证的最佳实践,确保系统安全性。希望这些建议能帮助您解决问题。如果您有更多疑问,请随时提出。