Проверяющий сервер выдает сертификаты Verisign Исключение сертификата недоверенного сервера
У меня проблема с проверкой сертификата Verisign при попытке соединения с HttpsURLConnection с нашим бэкэндом.
Текущая цепочка сертификации:$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: не доверенный сертификат сервера", и причина в том, что 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)"
2 ответа
Без дальнейшего кода я не могу сказать, но я вижу, что вы загружаете доверенные сертификаты, но где вы загружаете свой собственный Keystore? Если это в другом коде, я не могу сказать.
Также, что происходит, когда вы пытаетесь использовать внешний Truststore, например, $JAVA_HOME/jre/lib/security/cacerts
Предполагая, что вы действительно хотите использовать динамическое хранилище доверия (обычно они довольно статичны), взгляните на
http://jcalcote.wordpress.com/2010/06/22/managing-a-dynamic-java-trust-store/
Как было сказано ранее, хранилище TrustStore внутри JVM является статическим, после инициализации сертификаты не могут быть добавлены к нему (как я заметил с аналогичной проблемой). Простым решением является добавление ваших сертификатов к сертификату по умолчанию: $JAVA_HOME/jre/lib/security/cacerts
Или попробуйте включить код инициализации TrustStore в статический блок {}, чтобы быстрее его инициализировать и получить возможность обойти поведение по умолчанию.
Вы также можете использовать пользовательский файл KeysStore и попросить jvm использовать его с параметрами -Djavax.net.ssl.keyStore*.