導致產生 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
沒有留言:
張貼留言