2013-04-12 55 views
1

我嘗試通過java的內置功能(HttpURLConnection)進行https連接。但是,我得到這個異常:Java中的證書路徑發現

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) 
... 
... 

我的證書鏈是:

Root certificate -> Intermediate certificate -> Web server certificate

所使用的證書是正確的「路徑發現」的含義。信任錨點是根證書,它被導入到我的系統上的java密鑰庫中。中間證書不是...但

  1. 中間證書是由我信任的根簽名 - 所以我也相信中間人。
  2. Web服務器證書與中級證書籤名,這我相信(1點)

因此在驗證時必須順利通過?我錯了嗎?

我曾讀到這樣的:

瀏覽器可以做到自動發現,服務器對服務器沒有。

但是沒有這個功能是非常基本的。有沒有明確的做法auto-discovery

* *更新

是的,這是問題,GPI。我很困惑,因爲瀏覽器可以驗證服務器證書,但Java應用程序不能。 這種行爲的原因是:

  • 服務器只發送最後的證書,而不是整個證書 鏈;
  • 該證書最近被收購併且相對於 簽署了新的中間證書;
  • 瀏覽器有相對最新的證書列表 包括中間證書;
  • java有相對不是最新的證書列表,並且 中間證書不在裏面。
  • 瀏覽器驗證中間的最終證書 證書java無法檢查證書鏈,因爲:1. 鏈未被髮送; 2.最終證書的簽署者(中間名爲 )不是一個信任錨。

的解決方案可能是:

  • 服務器返回的整個證書鏈
  • 中間證書與Java信任存儲

回答

3

我相信你已經檢查您的鏈條,所以我們可以想當然地認爲RootCert簽署IntermediateCertIntermediateCert簽署ServerCert,憑有效X500名稱鏈接和所有...

也就是說,您的邏輯是有效的,即相信RootCert就足夠了,但不要忘記,爲了構建路徑,您的客戶端必須在其所有所有路徑中具有證書。

就你而言,如果只信任根證書,則由服務器通告證書鏈的其餘部分(中間和最終)。如果沒有人向HTTP客戶端提供中間證書,則客戶端將從服務器不知道中斷是不可能的。

通過使用-Djavax.net.debug=all選項啓動客戶端,您實際上可以看到您的服務器證書鏈。如果鏈的長度爲1,那麼你的服務器只會通告最終的證書,客戶無法猜測中間證書是否存在。

(也可以使用瀏覽器檢查並要求查看服務器證書,但您應該注意,瀏覽器會向您顯示完整路徑直至信任錨點,因此如果您想要推斷服務器鏈是什麼,你必須從這條路徑中刪除瀏覽器的錨點)。

在生產服務上,您應該引用您的證書提供商的網站,以瞭解什麼是根證書(可能不是最高級別的證書)。這個有效的根應該是你的客戶端的信任錨點,任何服務器都應該從路徑中最後一個(通用名稱是服務器的DNS名稱)的鏈中至少發佈所有其他的證書。

0

加入爲了通過HTTPS連接你需要使用HttpsURLConnection對象。您不能使用HttpURLConnection對象創建連接。

+1

URL serverUrl = new URL(serverAddress); connection =(HttpURLConnection)serverUrl.openConnection(); 是的,返回的對象是HttpsURLConnection,但它繼承HttpURLConnection。 – joro

相關問題