背景
在使用第三方 SDK 调用 API 时,本地开发环境通常能正常运行。但在现场服务器无外网的环境下,需要通过内外网代理来实现 API 调用,这时往往会遇到 SSL 证书校验失败的问题。
常规做法中,为了省事可能会直接跳过 SSL 校验(如 SslUtil.ignoreSsl()),但这次使用的 SDK 内部封装了 OkHttp 对象,无法通过公共方式全局绕过校验。因此,我们需要在'阳光大道'上找到一条合规的路径,确保证书校验顺利通过。
问题排查
现场使用 Nginx 进行代理转发,未配置有效证书的情况下,后台直接报错:
SSLHandshakeException: sun.security.validator.ValidatorException:
PKIX path building failed: sun.security.provider.certpath.SunCertPathBuilderException:
unable to find valid certification path to requested target
这个错误表明 Java 客户端无法验证目标服务器的证书链。排查 Nginx 日志为空,说明请求已到达,但 Java 端拦截并提示找不到有效的证书路径。在不走代理的情况下可以直接访问 API,问题出在 Java 向 Nginx 索要证书时,Nginx 返回的可能是自签名证书或证书不匹配。
这就好比用户要访问阿里云 API,Java 要求提供 aliyuncs.com 的证书,而 Nginx 却给了一个自签的 https.crt。Java 发现证书不可信,自然就会抛出异常。
解决方案
既然 Nginx 返回的证书不被 Java 认可,我们就需要手动将目标域名的证书导入到 Java 的信任库中。核心思路是:获取第三方 API 对应的证书文件,并将其添加到 Java 的 cacerts 信任库中,确保请求地址、Java 信任库证书与 Nginx 证书三者一致。
1. 导出目标域名证书
对于单个域名,可以使用 OpenSSL 工具导出证书。以阿里云 DashScope 为例:
D:\OpenSSL-Win64\bin\openssl.exe s_client -connect dashscope.aliyuncs.com:443 -servername dashscope.aliyuncs.com <NUL 2>NUL | D:\OpenSSL-Win64\bin\openssl.exe x509 -outform PEM -out F:/dashscope.crt
如果有多个请求地址需要生成组合域名的证书文件,建议参考相关文档进行多域名 HTTPS 配置。
2. 导入证书到 Java 信任库
拿到证书文件后,必须将其导入 Java 信任库,否则 Java 依然不会认可该证书。使用 keytool 命令即可:
keytool -import -alias amapaliyun-www -keystore "D:\JDK1.8\jre\lib\security\cacerts" -file "D:\nginx-1.19.7_B\conf\cert\amapaliyun.crt" -storepass changeit -noprompt
执行成功后,可以通过以下命令查看信任库中的证书信息,确认导入是否生效:
keytool -list -keystore "D:\JDK1.8\jre\lib\security\cacerts" -alias amapaliyun-www -storepass changeit
3. 重启服务验证
完成上述配置后,重新启动应用服务和 Nginx,再次进行测试验证。此时 Java 客户端应该能够正常识别证书,握手成功。
总结
遇到此类问题时,定位是关键。只有先明确报错是由 Java 信任库校验机制引起的,才能对症下药。很多时候我们容易在生成的证书本身是否有效上纠结太久,其实查看 Nginx 日志往往能快速划分责任边界。记录一下这个排查过程,希望能帮到有同样困扰的同行。

