在使用 Spring Boot + RestTemplate 調用 HTTPS 接口時,很多同學會遇到類似下面的報錯:
javax.net.ssl.SSLHandshakeException:
PKIX path building failed:
sun.security.provider.certpath.SunCertPathBuilderException:
unable to find valid certification path to requested target
這類錯誤通常意味著:JVM 無法信任目標服務返回的證書。
一、為什么會出現 PKIX path building failed?
PKIX path building failed
的意思是 證書鏈校驗失敗,JVM 在校驗證書時沒有找到可信的路徑。常見原因有以下幾種:
1. JDK 版本過舊
較早的 JDK(如 JDK8u101 之前)默認內置的 CA 根證書庫較老。
如果目標網站使用了新 CA(例如 Let's Encrypt 2021 年更新過根證書),老 JDK 可能無法識別。
2. 服務器證書鏈不完整
有些服務器只配置了 站點證書,但忘記安裝 中間證書。
瀏覽器會自動幫你補全中間證書,所以能正常訪問;
但 JVM 不會自動補全,導致校驗失敗。
3. 證書域名不匹配
如果訪問
https://example.com
,但證書只簽發給了api.example.com
,也會校驗失敗。
4. 使用了自簽名證書
內網測試時常見,需要手動導入證書到 JDK 信任庫。
二、如何排查?
檢查證書鏈是否完整
openssl s_client -connect yourdomain.com:443 -showcerts
如果只輸出一段證書而沒有中間 CA,說明配置不完整。
檢查域名是否匹配
openssl s_client -connect yourdomain.com:443 | openssl x509 -noout -text | grep DNS:
看 SAN 字段里是否包含你訪問的域名。
檢查 JDK 版本
java -version
建議 JDK8 至少升級到 8u202+ 或者直接使用 JDK11/17。
三、解決方案
方案一:升級 JDK(推薦)
如果你使用的是公有 CA 簽發的證書(DigiCert、GlobalSign、Let's Encrypt 等),一般不需要手動導入證書。
只要 JDK 足夠新,并且目標服務器配置了完整證書鏈,就可以正常使用。
方案二:修復服務器證書鏈
如果你是目標服務的維護方,確保服務器正確安裝了 完整證書鏈:
站點證書
中間證書
根證書(通常不需要手動安裝)
Nginx 示例配置:
ssl_certificate fullchain.pem; # 包含站點證書 + 中間證書
ssl_certificate_key privkey.pem;
方案三:導入證書到 JDK 信任庫(自簽名或內部 CA)
如果必須調用自簽名 HTTPS 服務,可以手動導入證書:
keytool -import -alias myserver \-keystore $JAVA_HOME/jre/lib/security/cacerts \-file server.crt
默認密碼:changeit
方案四:跳過 SSL 驗證(僅限開發測試)
在測試環境,可以讓 RestTemplate 忽略證書校驗:
public static RestTemplate insecureRestTemplate() throws Exception {TrustManager[] trustAllCerts = new TrustManager[]{new X509TrustManager() {public void checkClientTrusted(X509Certificate[] chain, String authType) {}public void checkServerTrusted(X509Certificate[] chain, String authType) {}public X509Certificate[] getAcceptedIssuers() { return new X509Certificate[0]; }}};SSLContext sslContext = SSLContext.getInstance("TLS");sslContext.init(null, trustAllCerts, new java.security.SecureRandom());HttpComponentsClientHttpRequestFactory factory = new HttpComponentsClientHttpRequestFactory();factory.setHttpClient(HttpClients.custom().setSSLContext(sslContext).setSSLHostnameVerifier(NoopHostnameVerifier.INSTANCE).build());return new RestTemplate(factory);
}
四、總結
如果是 公有 CA 簽發的證書,通常不需要額外配置,只要:
JDK 版本足夠新
目標服務器安裝了完整證書鏈
就能解決。
如果是 內部/自簽名證書,需要手動導入到 JDK 信任庫。
開發環境臨時調試,可以使用 跳過 SSL 驗證的 RestTemplate,但千萬不要在生產使用。