You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Spring应用调用Google Sheets API时出现SSLHandshakeException问题

Spring调用Google Sheets API时的SSLHandshakeException问题排查与解决

错误信息

javax.net.ssl.SSLHandshakeException: PKIX path building failed: sun.security.provider.certpath.SunCertPathBuilderException: unable to find valid certification path to requested target
    at java.base/sun.security.ssl.Alert.createSSLException(Alert.java:131) ~[na:na]
    at java.base/sun.security.ssl.TransportContext.fatal(TransportContext.java:371) ~[na:na]
    at java.base/sun.security.ssl.TransportContext.fatal(TransportContext.java:314) ~[na:na]
    at java.base/sun.security.ssl.TransportContext.fatal(TransportContext.java:309) ~[na:na]
    at java.base/sun.security.ssl.CertificateMessage$T12CertificateConsumer.checkServerCerts(CertificateMessage.java:654) ~[na:na]
    at java.base/sun.security.ssl.CertificateMessage$T12CertificateConsumer.onCertificate(CertificateMessage.java:473) ~[na:na]
    at java.base/sun.security.ssl.CertificateMessage$T12CertificateConsumer.consume(CertificateMessage.java:369) ~[na:na]
    at java.base/sun.security.ssl.SSLHandshake.consume(SSLHandshake.java:396) ~[na:na]
    at java.base/sun.security.ssl.HandshakeContext.dispatch(HandshakeContext.java:480) ~[na:na]
    at java.base/sun.security.ssl.HandshakeContext.dispatch(HandshakeContext.java:458) ~[na:na]
    at java.base/sun.security.ssl.TransportContext.dispatch(TransportContext.java:201) ~[na:na]
    at java.base/sun.security.ssl.SSLTransport.decode(SSLTransport.java:172) ~[na:na]
    at java.base/sun.security.ssl.SSLSocketImpl.decode(SSLSocketImpl.java:1500) ~[na:na]
    at java.base/sun.security.ssl.SSLSocketImpl.readHandshakeRecord(SSLSocketImpl.java:1415) ~[na:na]
    at java.base/sun.security.ssl.SSLSocketImpl.startHandshake(SSLSocketImpl.java:450) ~[na:na]
    at java.base/sun.security.ssl.SSLSocketImpl.startHandshake(SSLSocketImpl.java:421) ~[na:na]
    at java.base/sun.net.www.protocol.https.HttpsClient.afterConnect(HttpsClient.java:580) ~[na:na]

已尝试操作

  • 获取Google Sheets证书:
    echo | openssl s_client -servername sheets.googleapis.com -connect sheets.googleapis.com:443 2>/dev/null | openssl x509 > google_certificate5.crt
    
  • 将证书导入JDK信任库:
    sudo keytool -importcert -trustcacerts -file /Users/pavel1709/Desktop/google_certificate5.crt -alias googleCert5 -keystore /Library/Java/JavaVirtualMachines/jdk-17.jdk/Contents/Home/lib/security/cacerts
    
    操作后提示Certificate was added to keystore,但错误依旧。
  • 检查并手动设置信任库路径:
    System.out.println("javax.net.ssl.trustStore = " + System.getProperty("javax.net.ssl.trustStore")); // 输出null
    System.setProperty("javax.net.ssl.trustStore", "/Library/Java/JavaVirtualMachines/jdk-17.jdk/Contents/Home/lib/security/cacerts");
    
    设置后问题仍未解决。

可行解决方向

1. 导入完整证书链而非单张证书

Google的SSL证书采用链式结构,直接导出的服务器证书缺少中间CA证书,导致验证失败。执行以下命令导出完整证书链:

echo | openssl s_client -servername sheets.googleapis.com -connect sheets.googleapis.com:443 2>/dev/null | openssl crl2pkcs7 -nocrl -certfile /dev/stdin | openssl pkcs7 -print_certs -out google_full_chain.crt

再将完整链证书导入信任库:

sudo keytool -importcert -trustcacerts -file /Users/pavel1709/Desktop/google_full_chain.crt -alias googleFullChain -keystore /Library/Java/JavaVirtualMachines/jdk-17.jdk/Contents/Home/lib/security/cacerts

2. 确认应用实际使用的JDK版本

检查Spring运行时的JDK路径,确保和导入证书的JDK一致:

System.out.println("Java Home: " + System.getProperty("java.home"));

如果输出路径与目标JDK不符,需将证书导入应用实际使用的JDK的cacerts库。

3. 验证证书是否成功导入

用以下命令检查信任库中是否存在目标证书:

keytool -list -keystore /Library/Java/JavaVirtualMachines/jdk-17.jdk/Contents/Home/lib/security/cacerts -alias googleCert5

若提示Alias does not exist,说明之前导入操作失败,需重新导入并确认密码(默认密码为changeit)。

4. 通过JVM启动参数设置信任库

代码中设置属性可能在Spring初始化后生效,建议通过JVM启动参数传递:

-Djavax.net.ssl.trustStore=/Library/Java/JavaVirtualMachines/jdk-17.jdk/Contents/Home/lib/security/cacerts
-Djavax.net.ssl.trustStorePassword=changeit

Spring Boot应用可在application.properties中配置:

spring.jvm.args=-Djavax.net.ssl.trustStore=/Library/Java/JavaVirtualMachines/jdk-17.jdk/Contents/Home/lib/security/cacerts -Djavax.net.ssl.trustStorePassword=changeit

5. 排查网络代理/防火墙干扰

若网络环境存在代理或防火墙,可能拦截SSL连接导致验证失败。尝试关闭代理,或配置Spring应用的代理SSL信任规则。

内容的提问来源于stack exchange,提问作者Pavel Molchanov

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.23 22:25:16