2012-11-29 314 views
50

我得到了以下異常時,試圖張貼到HTTP服務器的請求:如何忽略PKIX路徑構建失敗:sun.security.provider.certpath.SunCertPathBuilderException?

下面是我用

URL url = new URL(
     "https://www.abc.com"); 
HttpURLConnection conn = (HttpURLConnection) url.openConnection(); 

conn.setRequestMethod("GET"); 

conn.setDoOutput(true); 

DataOutputStream wr = new DataOutputStream(conn.getOutputStream()); 
// wr.writeBytes(params); 
wr.flush(); 
wr.close(); 

BufferedReader br = new BufferedReader(new InputStreamReader(
     conn.getInputStream())); 
String line = null; 
while ((line = br.readLine()) != null) { 
    System.out.println(line); 
} 

下面的代碼是例外:

Exception in thread "main" 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 
    at com.sun.net.ssl.internal.ssl.Alerts.getSSLException(Alerts.java:174) 
    at com.sun.net.ssl.internal.ssl.SSLSocketImpl.fatal(SSLSocketImpl.java:1731) 
    at com.sun.net.ssl.internal.ssl.Handshaker.fatalSE(Handshaker.java:241) 
    at com.sun.net.ssl.internal.ssl.Handshaker.fatalSE(Handshaker.java:235) 
    at com.sun.net.ssl.internal.ssl.ClientHandshaker.serverCertificate(ClientHandshaker.java:1206) 
    at com.sun.net.ssl.internal.ssl.ClientHandshaker.processMessage(ClientHandshaker.java:136) 
    at com.sun.net.ssl.internal.ssl.Handshaker.processLoop(Handshaker.java:593) 
    at com.sun.net.ssl.internal.ssl.Handshaker.process_record(Handshaker.java:529) 
    at com.sun.net.ssl.internal.ssl.SSLSocketImpl.readRecord(SSLSocketImpl.java:925) 
    at com.sun.net.ssl.internal.ssl.SSLSocketImpl.performInitialHandshake(SSLSocketImpl.java:1170) 
    at com.sun.net.ssl.internal.ssl.SSLSocketImpl.startHandshake(SSLSocketImpl.java:1197) 
    at com.sun.net.ssl.internal.ssl.SSLSocketImpl.startHandshake(SSLSocketImpl.java:1181) 
    at sun.net.www.protocol.https.HttpsClient.afterConnect(HttpsClient.java:434) 
    at sun.net.www.protocol.https.AbstractDelegateHttpsURLConnection.connect(AbstractDelegateHttpsURLConnection.java:166) 
    at sun.net.www.protocol.http.HttpURLConnection.getOutputStream(HttpURLConnection.java:1014) 
    at sun.net.www.protocol.https.HttpsURLConnectionImpl.getOutputStream(HttpsURLConnectionImpl.java:230) 
    at com.amazon.mzang.tools.httpchecker.CategoryYank.getPV(CategoryYank.java:32) 
    at com.amazon.mzang.tools.httpchecker.CategoryYank.main(CategoryYank.java:18) 
Caused by: sun.security.validator.ValidatorException: PKIX path building failed: sun.security.provider.certpath.SunCertPathBuilderException: unable to find valid certification path to requested target 
    at sun.security.validator.PKIXValidator.doBuild(PKIXValidator.java:323) 
    at sun.security.validator.PKIXValidator.engineValidate(PKIXValidator.java:217) 
    at sun.security.validator.Validator.validate(Validator.java:218) 
    at com.sun.net.ssl.internal.ssl.X509TrustManagerImpl.validate(X509TrustManagerImpl.java:126) 
    at com.sun.net.ssl.internal.ssl.X509TrustManagerImpl.checkServerTrusted(X509TrustManagerImpl.java:209) 
    at com.sun.net.ssl.internal.ssl.X509TrustManagerImpl.checkServerTrusted(X509TrustManagerImpl.java:249) 
    at com.sun.net.ssl.internal.ssl.ClientHandshaker.serverCertificate(ClientHandshaker.java:1185) 
    ... 13 more 
Caused by: sun.security.provider.certpath.SunCertPathBuilderException: unable to find valid certification path to requested target 
    at sun.security.provider.certpath.SunCertPathBuilder.engineBuild(SunCertPathBuilder.java:174) 
    at java.security.cert.CertPathBuilder.build(CertPathBuilder.java:238) 
    at sun.security.validator.PKIXValidator.doBuild(PKIXValidator.java:318) 
    ... 19 more 

的服務器不屬於我。有沒有辦法忽略這個異常?

+5

不要忽略* *此異常。在您的信任商店中導入證書(經過一些手動驗證)。忽略證書錯誤會使連接容易受到潛在的MITM攻擊。 – Bruno

+8

有時候,信任對客戶端來說並不重要,但服務器已經使用https了。 – Gus

回答

44

如果你想忽略證書一起再看看答案在這裏:Ignore self-signed ssl cert using Jersey Client

雖然這會令您的應用程序容易受到中間人中間人攻擊。

或者,嘗試將證書添加到您的Java商店作爲一個可信任的證書。 這個網站可能會有幫助。 http://blog.icodejava.com/tag/get-public-key-of-ssl-certificate-in-java/

這是另一個線程,顯示如何將證書添加到您的商店。 Java SSL connect, add server cert to keystore programmatically

的關鍵是:

KeyStore.Entry newEntry = new KeyStore.TrustedCertificateEntry(someCert); 
ks.setEntry("someAlias", newEntry, null); 
28

我用下面的代碼覆蓋SSL在我的項目檢查,併爲我工作。

package com.beingjavaguys.testftp; 

import java.io.InputStreamReader; 
import java.io.Reader; 
import java.net.URL; 
import java.net.URLConnection; 

import javax.net.ssl.HostnameVerifier; 
import javax.net.ssl.HttpsURLConnection; 
import javax.net.ssl.SSLContext; 
import javax.net.ssl.SSLSession; 
import javax.net.ssl.TrustManager; 
import javax.net.ssl.X509TrustManager; 
import java.security.cert.X509Certificate; 

/** 
* Fix for Exception in thread "main" 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 
*/ 
public class ConnectToHttpsUrl { 
    public static void main(String[] args) throws Exception { 
     /* Start of Fix */ 
     TrustManager[] trustAllCerts = new TrustManager[] { new X509TrustManager() { 
      public java.security.cert.X509Certificate[] getAcceptedIssuers() { return null; } 
      public void checkClientTrusted(X509Certificate[] certs, String authType) { } 
      public void checkServerTrusted(X509Certificate[] certs, String authType) { } 

     } }; 

     SSLContext sc = SSLContext.getInstance("SSL"); 
     sc.init(null, trustAllCerts, new java.security.SecureRandom()); 
     HttpsURLConnection.setDefaultSSLSocketFactory(sc.getSocketFactory()); 

     // Create all-trusting host name verifier 
     HostnameVerifier allHostsValid = new HostnameVerifier() { 
      public boolean verify(String hostname, SSLSession session) { return true; } 
     }; 
     // Install the all-trusting host verifier 
     HttpsURLConnection.setDefaultHostnameVerifier(allHostsValid); 
     /* End of the fix*/ 

     URL url = new URL("https://nameofthesecuredurl.com"); 
     URLConnection con = url.openConnection(); 
     Reader reader = new InputStreamReader(con.getInputStream()); 
     while (true) { 
      int ch = reader.read(); 
      if (ch == -1) 
       break; 
      System.out.print((char) ch); 
     } 
    } 
} 
+0

不服從合同。 – EJP

+0

謝謝Kishore,在本地測試的好例子 –

+0

在你調用sc.init()時,第三個參數可能是null。 (將提供默認值。) – kevinarpe

15

設置validateTLSCertificates屬性falseJSoup命令。

Jsoup.connect("https://google.com/").validateTLSCertificates(false).get(); 
4

FWIW,在Ubuntu 10.04.2 LTS安裝CA證書,Java和固定這個問題對我來說,CA證書包。

+0

Omg經過6個小時的戰鬥我的舊的Ubuntu 10.04 VM,這解決了那個討厭的錯誤。這個版本太舊了,我不得不修改sources.list作爲那些返回的包404 https://askubuntu.com/questions/805523/apt-get-update-for-ubuntu-10-04 – jpp1jpp1

0

我在執行下面的spring-boot + RestAssured簡單測試時遇到了同樣的錯誤。

import org.junit.Test; 
import org.junit.runner.RunWith; 
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; 

import static com.jayway.restassured.RestAssured.when; 
import static org.apache.http.HttpStatus.SC_OK; 

@RunWith(SpringJUnit4ClassRunner.class) 
public class GeneratorTest { 

@Test 
public void generatorEndPoint() { 
    when().get("https://bal-bla-bla-bla.com/generators") 
      .then().statusCode(SC_OK); 
    } 
} 

在我的情況下,簡單的解決方法是添加 'useRelaxedHTTPSValidations()'

RestAssured.useRelaxedHTTPSValidation(); 

然後測試看起來像

import org.junit.Test; 
import org.junit.runner.RunWith; 
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; 

import static com.jayway.restassured.RestAssured.when; 
import static org.apache.http.HttpStatus.SC_OK; 

@RunWith(SpringJUnit4ClassRunner.class) 
public class GeneratorTest { 

@Before 
public void setUp() { 
    RestAssured.useRelaxedHTTPSValidation(); 
} 


@Test 
public void generatorEndPoint() { 
    when().get("https://bal-bla-bla-bla.com/generators") 
      .then().statusCode(SC_OK); 
    } 
} 
相關問題