呼叫 HTTPS 服務時拋出經典異常:
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
JRE 內建的信任憑證庫(cacerts)不包含目標伺服器憑證鏈的根憑證,導致信任鏈驗證中斷。
| 方案 | 優點 | 缺點 | 推薦度 |
|---|---|---|---|
| 匯入根憑證到 cacerts | 根治問題,安全性完整,一次配置永久生效 | 需重啟 JVM;需管理員權限 | ⭐⭐⭐⭐⭐ 首選 |
| 程式碼忽略信任驗證 | 快速繞過,適合測試環境 | 嚴重安全風險,生產環境嚴禁 | ⭐ 不推薦 |
server.cer# 找出實際執行的 JRE
ps -ef | grep java
# 或在程式中列印 System.getProperty("java.home")
# 確認 cacerts 存在且可寫
ls -l $JAVA_HOME/jre/lib/security/cacerts
# 若無寫入權限,需 sudo 或管理員執行 keytool
# 建議建立中繼 keystore 再批量匯入,避免直接操作 cacerts 風險
keytool -importcert -noprompt -trustcacerts \
-alias myserver -file server.cer \
-keystore /tmp/mykeystore -storepass changeit
# 將中繼 keystore 合併進 cacerts
keytool -importkeystore \
-srckeystore /tmp/mykeystore -srcstorepass changeit \
-destkeystore $JAVA_HOME/jre/lib/security/cacerts -deststorepass changeit
關鍵提醒:cacerts 預設密碼為 changeit 或 changeme。
# 列出已匯入別名
keytool -list -keystore $JAVA_HOME/jre/lib/security/cacerts | grep myserver
# 重啟 Java 應用程式
#!/bin/bash
# auto-import-cert.sh
HOSTPORT=$1
ALIAS=${2:-$(echo $HOSTPORT | tr ':' '_')}
openssl s_client -connect $HOSTPORT -showcerts /dev/null \
| openssl x509 -outform PEM > /tmp/${ALIAS}.pem
keytool -importcert -noprompt -trustcacerts \
-alias $ALIAS -file /tmp/${ALIAS}.pem \
-keystore $JAVA_HOME/jre/lib/security/cacerts -storepass changeit
RUN keytool ... 於建構階段固化,或掛載含自訂 cacerts 的 volume。