2014-01-10 5 views
9

Я использую «Дооснащение» для доступа к моему REST API. Однако, когда я поместил свой API за ssl и получил доступ к нему http://myhost/myapi, я получаю эту ошибку:javax.net.ssl.SSLHandshakeException: java.security.cert.CertPathValidatorException: Trust anchor для пути сертификации не найден

Нужно ли мне сделать что-то дополнительное, когда мой API находится за SSL?

Вот как я связываю:

private final String API = "https://myhost/myapi"; 

private final RestAdapter REST_ADAPTER = new RestAdapter.Builder() 
     .setServer(API) 
     .setLogLevel(RestAdapter.LogLevel.FULL) 
     .build(); 

01-10 09:49:55.621 2076-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) 
+0

вы решили эту проблему? –

+0

Если вы еще этого не решили, обратитесь к http://stackoverflow.com/a/31436459/4261176 –

ответ

0

Протокол SSL не настроен правильно. Эти ошибки trustAnchor обычно означают, что хранилище доверия не может быть найдено. Проверьте свою конфигурацию и убедитесь, что вы на самом деле указываете на хранилище доверия и что он на месте.

Убедитесь, что у вас есть системный набор -Djavax.net.ssl.trustStore, а затем проверьте, что путь фактически ведет к хранилищу доверия.

Вы также можете включить отладку SSL, установив эту системную собственность -Djavax.net.debug=all. В выводе отладки вы заметите, что он не может найти хранилище доверия.

+1

Я думаю, что это будет работать на Desktop Java, но не на Android. – Janusz

+0

Среднее, что сертификат партнера не был найден или не доверен хранилищу доверия, который * был * найден. – EJP

1

Есть 4 способа, которые я знаю:

  • импорта сертификата для вашего приложения и использовать его для подключения
  • проверки отключить сертификат
  • добавить сертификат в доверенные системы сертификатов в Android
  • купить проверить сертификат, принятое Android

Я предполагаю, что вы не хотят платить за это, так что я думаю, что самое элегантное решение является первым, что может быть достигнуто следующим образом:

http://blog.crazybob.org/2010/02/android-trusting-ssl-certificates.html

+0

Как я могу просто отключить проверку сертификатов? Желание сделать это только в тестовой среде. – theblang

+0

Как вы «добавляете свой сертификат к сертификатам надежной системы в Android»? –

+0

В Интернете есть несколько учебных пособий. Вот вам одно: http://www.guyrutenberg.com/2013/03/16/manually-install-ssl-certificate-in-android-jelly-bean/ – kupsef

0

Это может произойти по нескольким причинам, в том числе:

  1. CA, выдавший сертификат сервера, был неизвестен
  2. Сертификат сервера не был подписан ЦС, но был подписан сам по себе
  3. В конфигурации сервера отсутствует промежуточный CA

пожалуйста проверьте эту связь для решения: https://developer.android.com/training/articles/security-ssl.html#CommonProblems

+0

Поддерживает ли это решение решение с OkHttp? –

+0

Да, я использовал retrofit + okhttp к тому времени – Defuera

8

Причина это происходит является JVM/Dalvik не не уверены в ЦА сертификатов в системе или в хранилище сертификатов пользователя.

Чтобы исправить это с помощью Дооснащения, если вы используете 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 

CACERT=$1 
BCJAR=bcprov-jdk16-1.46.jar 

TRUSTSTORE=mytruststore.bks 
ALIAS=`openssl x509 -inform PEM -subject_hash -noout -in $CACERT` 

if [ -f $TRUSTSTORE ]; then 
    rm $TRUSTSTORE || exit 1 
fi 

echo "Adding certificate to $TRUSTSTORE..." 
keytool -import -v -trustcacerts -alias $ALIAS \ 
     -file $CACERT \ 
     -keystore $TRUSTSTORE -storetype BKS \ 
     -providerclass org.bouncycastle.jce.provider.BouncyCastleProvider \ 
     -providerpath $BCJAR \ 
     -storepass secret 

echo "" 
echo "Added '$CACERT' with alias '$ALIAS' to $TRUSTSTORE..." 

B). Скопируйте файл truststore mytruststore.bks в res/raw вашего проекта truststore location

C). Установка SSLContext соединения:

............. 
okHttpClient = new OkHttpClient(); 
try { 
    KeyStore ksTrust = KeyStore.getInstance("BKS"); 
    InputStream instream = context.getResources().openRawResource(R.raw.mytruststore); 
    ksTrust.load(instream, "secret".toCharArray()); 

    // TrustManager decides which certificate authorities to use. 
    TrustManagerFactory tmf = TrustManagerFactory 
     .getInstance(TrustManagerFactory.getDefaultAlgorithm()); 
    tmf.init(ksTrust); 
    SSLContext sslContext = SSLContext.getInstance("TLS"); 
    sslContext.init(null, tmf.getTrustManagers(), null); 

    okHttpClient.setSslSocketFactory(sslContext.getSocketFactory()); 
} catch (KeyStoreException | IOException | NoSuchAlgorithmException | CertificateException | KeyManagementException e) { 
    e.printStackTrace(); 
} 
................. 
+0

Если вы используете 'retrofit', вы должны прикрепить этот« OkHttpClient », как предлагается здесь: https://github.com/square/retrofit/issues/265. Кроме того, я нашел, что это работает только с: 'bcprov-jdk16-1.46.jar', иначе вы получите' неправильную версию keystore error' – surfer190

+0

Моя полная голова волос благодарит вас. – mwieczorek

2

Привет же проблема я решил, вы можете попробовать это

java.security.cert.CertPathValidatorException: Trust anchor for certification path not found.NETWORK

// SET SSL 
public static OkClient setSSLFactoryForClient(OkHttpClient client) { 
    try { 
     // Create a trust manager that does not validate certificate chains 
     final TrustManager[] trustAllCerts = new TrustManager[]{ 
       new X509TrustManager() { 
        @Override 
        public void checkClientTrusted(java.security.cert.X509Certificate[] chain, String authType) throws CertificateException { 
        } 

        @Override 
        public void checkServerTrusted(java.security.cert.X509Certificate[] chain, String authType) throws CertificateException { 
        } 

        @Override 
        public java.security.cert.X509Certificate[] getAcceptedIssuers() { 
         return null; 
        } 
       } 
     }; 

     // Install the all-trusting trust manager 
     final SSLContext sslContext = SSLContext.getInstance("SSL"); 
     sslContext.init(null, trustAllCerts, new java.security.SecureRandom()); 
     // Create an ssl socket factory with our all-trusting manager 
     final SSLSocketFactory sslSocketFactory = sslContext.getSocketFactory(); 


     client.setSslSocketFactory(sslSocketFactory); 
     client.setHostnameVerifier(new HostnameVerifier() { 
      @Override 
      public boolean verify(String hostname, SSLSession session) { 
       return true; 
      } 
     }); 

    } catch (Exception e) { 
     throw new RuntimeException(e); 
    } 
    return new OkClient(client); 
} 
+0

Отличное решение! для меня после траты 2 дня :) –

+1

помните, что это отключение проверки сертификата. избегайте его в производственных условиях! – logoff