2013-05-07 234 views
4

嘗試使用HttpsURLConnection連接到我們的後端時,驗證Verisign證書時出現問題。驗證服務器Verisign證書是否引發不受信任的服務器證書異常

當前證書鏈: $openssl s_client -connect host:443

0 s:/C=AT/ST=xxx/L=xxx/O=xxx/CN=host 
    i:/C=US/O=VeriSign, Inc./OU=VeriSign Trust Network/OU=Terms of use at https://www.verisign.com/rpa (c)10/CN=VeriSign Class 3 International Server CA - G3 

1 s:/C=US/O=VeriSign, Inc./OU=VeriSign Trust Network/OU=Terms of use at https://www.verisign.com/rpa (c)10/CN=VeriSign Class 3 International Server CA - G3 
    i:/C=US/O=VeriSign, Inc./OU=VeriSign Trust Network/OU=(c) 2006 VeriSign, Inc. - For authorized use only/CN=VeriSign Class 3 Public Primary Certification Auth 
ority - G5 

2 s:/C=US/O=VeriSign, Inc./OU=VeriSign Trust Network/OU=(c) 2006 VeriSign, Inc. - For authorized use only/CN=VeriSign Class 3 Public Primary Certification Auth 
ority - G5 
    i:/C=US/O=VeriSign, Inc./OU=Class 3 Public Primary Certification Authority 

3 s:/C=US/O=VeriSign, Inc./OU=Class 3 Public Primary Certification Authority 
    i:/C=US/O=VeriSign, Inc./OU=Class 3 Public Primary Certification Authority 

我敢肯定,我已經下載並添加所有證書到密鑰庫,但我仍然得到異常:「javax.net.ssl.SSLException:不受信任服務器證書「和原因是java.security.cert.CertificateException: java.security.cert.CertPathValidatorException: TrustAnchor found but certificate validation failed.

我獲得的連接代碼:

String keyStoreType = KeyStore.getDefaultType(); 
KeyStore keyStore = KeyStore.getInstance(keyStoreType); 
keyStore.load(null, null); 
keyStore.setCertificateEntry("verisign_0", getVerisign0()); 
keyStore.setCertificateEntry("verisign_1", getVerisign1()); 
keyStore.setCertificateEntry("verisign_2", getVerisign2()); 
keyStore.setCertificateEntry("verisign_3", getVerisign3()); 

String tmfAlgorithm = TrustManagerFactory.getDefaultAlgorithm(); 
TrustManagerFactory tmf = TrustManagerFactory.getInstance(tmfAlgorithm); 
tmf.init(keyStore); 

SSLContext context = SSLContext.getInstance("TLS"); 
context.init(null, tmf.getTrustManagers(), null); 

HttpsURLConnection urlConnection = (HttpsURLConnection) url.openConnection(); 
urlConnection.setSSLSocketFactory(context.getSocketFactory()); 
return urlConnection; 

問題正在發生,當調用connection.connect()時。所有的getVerisign()方法都會返回正確的證書。有沒有我忘記的一步?可能需要添加證書的特殊訂單?

只是爲了澄清,我已經使用這種技術與swisssign證書,它的工作。我面臨這個問題,因爲一些Android 2.1,2.2設備沒有一些根證書。提前致謝。

堆棧跟蹤:

[0] = {[email protected]}"org.apache.harmony.xnet.provider.jsse.TrustManagerImpl.checkServerTrusted(TrustManagerImpl.java:168)" 
[1] = {[email protected]}"org.apache.harmony.xnet.provider.jsse.OpenSSLSocketImpl.startHandshake(OpenSSLSocketImpl.java:366)" 
[2] = {[email protected]}"org.apache.harmony.luni.internal.net.www.protocol.http.HttpConnection.getSecureSocket(HttpConnection.java:168)" 
[3] = {[email protected]}"org.apache.harmony.luni.internal.net.www.protocol.https.HttpsURLConnectionImpl$HttpsEngine.connect(HttpsURLConnectionImpl.java:399)" 
[4] = {[email protected]}"org.apache.harmony.luni.internal.net.www.protocol.https.HttpsURLConnectionImpl.connect(HttpsURLConnectionImpl.java:147)" 
+0

證書是否過期或者CLR/OCSP URL無法訪問(甚至是已撤銷)? – 2013-05-16 12:19:02

+0

這只是一個提示,供您試用。我最近做了一個需要通過HTTPS與服務器進行通信的應用程序,它在4版本的HttpsURLConnection類中都可以正常工作,但是在所有其他情況下,它都返回不可信。我們的證書是Thawte頒發的。唯一的解決方案,畢竟通過論壇和主題進行搜索是與SSLSocket一起去。爲什麼這個工作和其他解決方案沒有我沒有找到任何合理的答案。希望這有助於並享受您的工作。 – 2013-05-15 00:35:57

+0

對不起,延遲發表評論,但我不在城裏。如果有人遇到simillar問題:由於我無法在安裝我們應用程序的每臺設備上安裝證書,因此我必須將設備的內部trustStore和我自己的trustStore與我的證書一起使用(如果第一個trustStore返回異常,將使用這些證書)。[參考](http://nelenkov.blogspot.sk/2011/12/using-custom-certificate-trust-store-on.html) – iBecar 2013-05-20 19:50:24

回答

2

如果沒有進一步的代碼,我不能告訴,但我可以看到你加載可信證書,但你在哪裏加載自己的密鑰庫?如果它在其他代碼中,我不能說。

當您嘗試使用外部信任庫時會發生什麼,例如$ JAVA_HOME/JRE/lib/security中/ cacerts的

假設你真的想用一個動態的信任庫(通常他們是相當靜態的),看看

http://jcalcote.wordpress.com/2010/06/22/managing-a-dynamic-java-trust-store/

2

和以前一樣,說: JVM中的TrustStore是靜態的,一旦初始化,就不能將證書添加到它中(正如我觀察到的類似問題)。 簡單的解決方案是將您的證書添加到默認之一:$ JAVA_HOME/JRE/lib/security中/ cacerts的

可以試一下包括您的信任初始化代碼到一個靜態{}塊越早初始化,並有機會繞過默認行爲。

您也可以使用自定義文件KeysStore並要求jvm將其與-Djavax.net.ssl.keyStore *參數一起使用。

相關問題