4

尝试将 HttpsURLConnection 连接到我们的后端时,我在验证 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

我很确定我已将所有证书下载并添加到 KeyStore 中,但我仍然收到异常:“ javax.net.ssl.SSLException: Not trust server certificate ”,原因是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] = {java.lang.StackTraceElement@830078967208}"org.apache.harmony.xnet.provider.jsse.TrustManagerImpl.checkServerTrusted(TrustManagerImpl.java:168)"
[1] = {java.lang.StackTraceElement@830078967584}"org.apache.harmony.xnet.provider.jsse.OpenSSLSocketImpl.startHandshake(OpenSSLSocketImpl.java:366)"
[2] = {java.lang.StackTraceElement@830078967960}"org.apache.harmony.luni.internal.net.www.protocol.http.HttpConnection.getSecureSocket(HttpConnection.java:168)"
[3] = {java.lang.StackTraceElement@830078968368}"org.apache.harmony.luni.internal.net.www.protocol.https.HttpsURLConnectionImpl$HttpsEngine.connect(HttpsURLConnectionImpl.java:399)"
[4] = {java.lang.StackTraceElement@830078968816}"org.apache.harmony.luni.internal.net.www.protocol.https.HttpsURLConnectionImpl.connect(HttpsURLConnectionImpl.java:147)"
4

2 回答 2

2

如果没有更多代码,我无法判断,但我可以看到您正在加载受信任的证书,但是您在哪里加载自己的密钥库?如果它在其他代码中,我无法判断。

此外,当您尝试使用外部信任库时会发生什么,例如 $JAVA_HOME/jre/lib/security/cacerts

假设您真的想使用动态信任存储(通常它们是非常静态的),请查看

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

于 2013-05-14T01:12:32.110 回答
2

如前所述,JVM 中的 TrustStore 是静态的,一旦初始化,就不能将证书附加到它上面(正如我观察到的类似问题)。简单的解决方案是将您的证书添加到默认证书:$JAVA_HOME/jre/lib/security/cacerts

或者尝试将您的 TrustStore 初始化代码包含到静态 {} 块中以更快地对其进行初始化并有机会绕过默认行为。

您还可以使用自定义文件 KeysStore 并要求 jvm 将其与 -Djavax.net.ssl.keyStore* 参数一起使用。

于 2013-05-15T14:30:50.103 回答