PKIX path building failed: sun.security.provider.certpath.SunCertPathBuilderException: unable to find valid certification path to requested target
Java 客戶端呼叫 HTTPS 服務時,因信任庫中無目標伺服器憑證導致 SSL 握手失敗。
將目標伺服器的 SSL 憑證匯入客戶端 JRE 的信任庫 (cacerts 或 jssecacerts)。
建立 InstallCert.java(來源:Sun/Oracle 官方範例),核心功能:連線目標主機、取得憑證鏈、寫入 jssecacerts。
代碼較長,此處略,關鍵類:SSLSocketFactory、X509TrustManager、KeyStore
# 進入 JDK bin 目錄 cd /usr/java/jdk1.8.0_xxx/bin # 編譯 javac /path/to/InstallCert.java # 執行:指定目標主機 (預設 port 443) java InstallCert www.cebbank.com
Loading KeyStore /usr/java/jdk1.8.0_xxx/jre/lib/security/cacerts... Opening connection to www.cebbank.com:443... Starting SSL handshake... javax.net.ssl.SSLHandshakeException: PKIX path building failed... Server sent 1 certificate(s): 1 Subject CN=www.cebbank.com, OU=..., O=China Everbright Bank Co., Ltd, L=Beijing Issuer CN=VeriSign Class 3 Extended Validation SSL CA... sha1 5b d2 85 6e ... md5 05 d8 ae ee ... Enter certificate to add to trusted keystore or 'q' to quit: [1] # 輸入 1 並 Enter
# 當前目錄下生成 jssecacerts cp jssecacerts $JAVA_HOME/jre/lib/security/
重啟 Tomcat/應用服務,SSL 握手即可成功。
// 僅供開發/測試使用,生產環境嚴禁
TrustManager[] trustAll = 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 sc = SSLContext.getInstance("TLS");
sc.init(null, trustAll, new SecureRandom());
HttpsURLConnection.setDefaultSSLSocketFactory(sc.getSocketFactory());
正式環境務必將伺服器憑證正規匯入信任庫;InstallCert 是標準無痛工具。切記:繞過驗證僅限測試,生產環境會造成中間人攻擊風險。