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 trusted 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

前に述べたように、JVM 内の TrustStore は静的であり、一度初期化すると、証明書を追加することはできません (同様の問題で観察したように)。簡単な解決策は、証明書をデフォルトのものに追加することです: $JAVA_HOME/jre/lib/security/cacerts

または、TrustStore の初期化コードを静的な {} ブロックに含めて、初期化を早め、デフォルトの動作をバイパスする機会を得るようにしてください。

また、カスタム ファイルの KeysStore を使用して、jvm に -Djavax.net.ssl.keyStore* パラメータでそれを使用するように依頼することもできます。

于 2013-05-15T14:30:50.103 に答える
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 に答える