導致產生 PKIX path building failed 這樣的例外,原因是開發環境/生產環境中的 Java 使用 HTTPS 時會使用 Java Home 目錄下的 SSL 憑證,這個預設憑證並沒有經過 CA 認證,因此不被 CA 認可過的證書不會被 Java 做 Https Request 時接受,另一個原因是 Java 存放 SSL 憑證的目錄並沒有可用的 SSL 憑證 (可以自己簽)。
本文所摘錄之解決方案是自行設計證書認證管理物件,將其中的證書檢驗方法覆寫且不做任何驗證,簡單的說就是跳過證書驗證,所以不適合在生產環境使用,若有中間人攻擊,則無法在程式中做防禦 。
程式碼:
private static String getURL(String https_url) throws NoSuchAlgorithmException, KeyManagementException{
//建立 CA 認證管理物件
TrustManager[] trustAllCerts = new TrustManager[] {
new X509TrustManager() {
public X509Certificate[] getAcceptedIssuers() {
return null;
}
public void checkClientTrusted(X509Certificate[] certs, String authType) {
//跳過驗證
}
public void checkServerTrusted(X509Certificate[] certs, String authType) {
//跳過驗證
}
}
};
SSLContext sslc = SSLContext.getInstance("TLS");
sslc.init(null, trustAllCerts, null);
LayeredConnectionSocketFactory lcsf = new SSLConnectionSocketFactory(sslc);
CloseableHttpClient clientObject = HttpClients.custom()
.setSSLSocketFactory(sslSocketFactory)
.build();
try {
HttpGet request = new HttpGet(https_url);
request.setHeader("User-Agent", "Mozilla/5.0 (Windows NT 6.1; WOW64) ...");
CloseableHttpResponse response = clientObject.execute(request);
BufferedReader br = new BufferedReader(new InputStreamReader(response.getEntity().getContent()));
String body = "";
String input;
while ((input = br.readLine()) != null){
body += input;
}
br.close();
return body;
} catch (MalformedURLException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
return "";
}
Reference:
https://confluence.atlassian.com/kb/unable-to-connect-to-ssl-services-due-to-pkix-path-building-failed-779355358.html
https://stackoverflow.com/questions/21076179/pkix-path-building-failed-and-unable-to-find-valid-certification-path-to-requ
https://www.mkyong.com/java/java-https-client-httpsurlconnection-example/
https://www.aneasystone.com/archives/2016/04/java-and-https.html
沒有留言:
張貼留言