2013-05-07 235 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 *参数一起使用。

相关问题