javax.net.ssl.SSLHandshakeException: java.security.cert.CertPathValidatorException: Trust anchor for certification path not found
javax.net.ssl.SSLHandshakeException: java.security.cert.Исключение CertPathValidatorException: привязка доверия для пути сертификации не найдена
Я использую Retrofit для доступа к моему REST API. Однако, когда я помещаю свой API за ssl и получаю к нему доступ с помощью http://myhost/myapi, я получаю эту ошибку:
Нужно ли мне делать что-то дополнительное теперь, когда мой API поддерживает SSL?
01-10 09:49:55.6212076-2100/com.myapp.mobile D/Retrofit﹕ javax.net.ssl.SSLHandshakeException: java.security.cert.CertPathValidatorException: Trust anchor for certification path not found. at org.apache.harmony.xnet.provider.jsse.OpenSSLSocketImpl.startHandshake(OpenSSLSocketImpl.java:401) at libcore.net.http.HttpConnection.setupSecureSocket(HttpConnection.java:209) at libcore.net.http.HttpsURLConnectionImpl$HttpsEngine.makeSslConnection(HttpsURLConnectionImpl.java:478) at libcore.net.http.HttpsURLConnectionImpl$HttpsEngine.connect(HttpsURLConnectionImpl.java:433) at libcore.net.http.HttpEngine.sendSocketRequest(HttpEngine.java:290) at libcore.net.http.HttpEngine.sendRequest(HttpEngine.java:240) at libcore.net.http.HttpURLConnectionImpl.getResponse(HttpURLConnectionImpl.java:282) at libcore.net.http.HttpURLConnectionImpl.getResponseCode(HttpURLConnectionImpl.java:497) at libcore.net.http.HttpsURLConnectionImpl.getResponseCode(HttpsURLConnectionImpl.java:134) at retrofit.client.UrlConnectionClient.readResponse(UrlConnectionClient.java:90) at retrofit.client.UrlConnectionClient.execute(UrlConnectionClient.java:48) at retrofit.RestAdapter$RestHandler.invokeRequest(RestAdapter.java:287) at retrofit.RestAdapter$RestHandler.invoke(RestAdapter.java:222) at $Proxy12.signin(Native Method) at com.myapp.loginactivity$3.doInBackground(LoginActivity.java:143) at com.myapp.loginactivity$3.doInBackground(LoginActivity.java:136) at android.os.AsyncTask$2.call(AsyncTask.java:287) at java.util.concurrent.FutureTask.run(FutureTask.java:234) at android.os.AsyncTask$SerialExecutor$1.run(AsyncTask.java:230) at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1080) at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:573) at java.lang.Thread.run(Thread.java:841) Caused by: java.security.cert.CertificateException: java.security.cert.CertPathValidatorException: Trust anchor for certification path not found. at org.apache.harmony.xnet.provider.jsse.TrustManagerImpl.checkTrusted(TrustManagerImpl.java:282) at org.apache.harmony.xnet.provider.jsse.TrustManagerImpl.checkServerTrusted(TrustManagerImpl.java:202) at org.apache.harmony.xnet.provider.jsse.OpenSSLSocketImpl.verifyCertificateChain(OpenSSLSocketImpl.java:595) at org.apache.harmony.xnet.provider.jsse.NativeCrypto.SSL_do_handshake(Native Method) at org.apache.harmony.xnet.provider.jsse.OpenSSLSocketImpl.startHandshake(OpenSSLSocketImpl.java:398) at libcore.net.http.HttpConnection.setupSecureSocket(HttpConnection.java:209) at libcore.net.http.HttpsURLConnectionImpl$HttpsEngine.makeSslConnection(HttpsURLConnectionImpl.java:478) at libcore.net.http.HttpsURLConnectionImpl$HttpsEngine.connect(HttpsURLConnectionImpl.java:433) at libcore.net.http.HttpEngine.sendSocketRequest(HttpEngine.java:290) at libcore.net.http.HttpEngine.sendRequest(HttpEngine.java:240) at libcore.net.http.HttpURLConnectionImpl.getResponse(HttpURLConnectionImpl.java:282) at libcore.net.http.HttpURLConnectionImpl.getResponseCode(HttpURLConnectionImpl.java:497) at libcore.net.http.HttpsURLConnectionImpl.getResponseCode(HttpsURLConnectionImpl.java:134) at retrofit.client.UrlConnectionClient.readResponse(UrlConnectionClient.java:90) at retrofit.client.UrlConnectionClient.execute(UrlConnectionClient.java:48) at retrofit.RestAdapter$RestHandler.invokeRequest(RestAdapter.java:287) at retrofit.RestAdapter$RestHandler.invoke(RestAdapter.java:222) at $Proxy12.signin(Native Method) at com.myapp.LoginActivity$3.doInBackground(LoginActivity.java:143) at com.myapp.LoginActivity$3.doInBackground(LoginActivity.java:136) at android.os.AsyncTask$2.call(AsyncTask.java:287) at java.util.concurrent.FutureTask.run(FutureTask.java:234) at android.os.AsyncTask$SerialExecutor$1.run(AsyncTask.java:230) at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1080) at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:573) at java.lang.Thread.run(Thread.java:841)
Переведено автоматически
Ответ 1
Причина, по которой это происходит, заключается в том, что JVM / Dalvik не уверены в сертификатах CA в системе или в хранилищах пользовательских сертификатов.
Чтобы исправить это с помощью Retrofit, если вы используете okhttp, с другим клиентом это очень похоже. Вам нужно сделать:
A). Создайте хранилище сертификатов, содержащее открытый ключ CA. Для этого вам нужно запустить следующий скрипт для * nix. Вам необходимо установить openssl на свой компьютер и загрузить с https://www.bouncycastle.org / jar bcprov-jdk16-1.46.jar. Загружайте эту версию, а не другую, версия 1.5x несовместима с Android 4.0.4.
#!/bin/bash
if [ -z $1 ]; then echo "Usage: cert2Android<CA cert PEM file>" exit 1 fi
В принципе, у вас есть четыре потенциальных решения для исправления исключения "javax.net.ssl.SSLHandshakeException: " на Android
Доверяйте всем сертификатам. Не делайте этого, если вы действительно не знаете, что делаете.
Создайте пользовательский SSLSocketFactory, который доверяет только вашему сертификату. Это работает до тех пор, пока вы точно знаете, к каким серверам собираетесь подключаться, но как только вам потребуется подключиться к новому серверу с другим SSL-сертификатом, вам потребуется обновить ваше приложение.
Создайте файл хранилища ключей, содержащий "основной список" сертификатов Android, затем добавьте свой собственный. Если срок действия какого-либо из этих сертификатов истекает в будущем, вы несете ответственность за их обновление в своем приложении. Я не могу придумать причину для этого.
Создайте пользовательский SSLSocketFactory, который использует встроенное хранилище ключей сертификата, но использует альтернативное хранилище ключей для всего, что не удается проверить по умолчанию. Это хорошо объяснено в нажмите здесь
Кроме того, я хочу подробнее остановиться на пункте № 1. Мы можем выборочно пропустить некоторый домен, используя manifest network config в качестве объяснения:
Создайте файл "network_security_config.xml" в папке xml в папке res со следующим содержимым.