2015-10-11 2 views
4

В моем приложении для Android мне нужно выполнить некоторый запрос на мой сервер с помощью библиотеки OkHttp. У меня есть сертификат SSL, которые состоят из четырех частей:Сертификат доверия OkHttp

  • AddTrustExternalCARoot.crt
  • COMODORSAAddTrustCA.crt
  • COMODORSADomainValidationSecureServerCA.crt
  • www_mydomain_com.crt

я импортировал все части в portecle 1.9, затем я установил свой пароль хранилища ключей, и я экспортировал сертификат .bks.

Затем я вставил этот mycert.bks в папку res/raw моего проекта приложения. Теперь я пытаюсь подключиться к серверу по протоколу HTTPS с этим кодом:

OkHttpClient client = new OkHttpClient(); 
     try{ 
      client.setSslSocketFactory(getPinnedCertSslSocketFactory(context)); 
      RequestBody formBody = new FormEncodingBuilder() 
        .add("params", "xxx") 
        .build(); 
      Request request = new Request.Builder() 
        .url("https:\\mydomain.com") 
        .post(formBody) 
        .build(); 

      Response response = client.newCall(request).execute(); 
      if (!response.isSuccessful()) throw new IOException("Unexpected code " + response); 
      return response.body().string();; 
     } catch (Exception e) { 
      e.printStackTrace(); 
     } 
     return null; 

    } 


private SSLSocketFactory getPinnedCertSslSocketFactory(Context context) { 
    try { 
     KeyStore trusted = KeyStore.getInstance("BKS"); 
     InputStream in = context.getResources().openRawResource(R.raw.mycert); 
     trusted.load(in, "mypass".toCharArray()); 
     SSLContext sslContext = SSLContext.getInstance("TLS"); 
     TrustManagerFactory trustManagerFactory = TrustManagerFactory.getInstance(
     TrustManagerFactory.getDefaultAlgorithm()); 
     trustManagerFactory.init(trusted); 
     sslContext.init(null, trustManagerFactory.getTrustManagers(), null); 
     return sslContext.getSocketFactory(); 
    } catch (Exception e) { 
     Log.e("MyApp", e.getMessage(), e); 
    } 
    return null; 
} 

Но я получаю исключение, это LogCat:

10-11 18:22:51.930 13604-5341/com.aaa.android.client W/System.err: javax.net.ssl.SSLPeerUnverifiedException: Hostname myserver.net not verified: 
10-11 18:22:51.930 13604-5341/com.aaa.android.client W/System.err:  certificate: sha1/"mysha1string" 
10-11 18:22:51.930 13604-5341/com.aaa.android.client W/System.err:  DN: CN=www.aaa.it,OU=PositiveSSL,OU=Domain Control Validated 
10-11 18:22:51.930 13604-5341/com.aaa.android.client W/System.err:  subjectAltNames: [www.aaa.it, aaa.it] 
10-11 18:22:51.940 13604-5341/com.aaa.android.client W/System.err:  at com.squareup.okhttp.Connection.connectTls(Connection.java:244) 
10-11 18:22:51.940 13604-5341/com.aaa.android.client W/System.err:  at com.squareup.okhttp.Connection.connectSocket(Connection.java:199) 
10-11 18:22:51.940 13604-5341/com.aaa.android.client W/System.err:  at com.squareup.okhttp.Connection.connect(Connection.java:172) 
10-11 18:22:51.940 13604-5341/com.aaa.android.client W/System.err:  at com.squareup.okhttp.Connection.connectAndSetOwner(Connection.java:367) 
10-11 18:22:51.940 13604-5341/com.aaa.android.client W/System.err:  at com.squareup.okhttp.OkHttpClient$1.connectAndSetOwner(OkHttpClient.java:128) 
10-11 18:22:51.940 13604-5341/com.aaa.android.client W/System.err:  at com.squareup.okhttp.internal.http.HttpEngine.connect(HttpEngine.java:328) 
10-11 18:22:51.940 13604-5341/com.aaa.android.client W/System.err:  at com.squareup.okhttp.internal.http.HttpEngine.sendRequest(HttpEngine.java:245) 
10-11 18:22:51.940 13604-5341/com.aaa.android.client W/System.err:  at com.squareup.okhttp.Call.getResponse(Call.java:267) 
10-11 18:22:51.940 13604-5341/com.aaa.android.client W/System.err:  at com.squareup.okhttp.Call$ApplicationInterceptorChain.proceed(Call.java:224) 
10-11 18:22:51.940 13604-5341/com.aaa.android.client W/System.err:  at com.squareup.okhttp.Call.getResponseWithInterceptorChain(Call.java:195) 
10-11 18:22:51.940 13604-5341/com.aaa.android.client W/System.err:  at com.squareup.okhttp.Call.execute(Call.java:79) 
10-11 18:22:51.940 13604-5341/com.aaa.android.client W/System.err:  at com.aaa.android.client.Login$BackgroundTask.doInBackground(Login.java:294) 
10-11 18:22:51.940 13604-5341/com.aaa.android.client W/System.err:  at com.aaa.android.client.Login$BackgroundTask.doInBackground(Login.java:277) 
10-11 18:22:51.950 13604-5341/com.aaa.android.client W/System.err:  at android.os.AsyncTask$2.call(AsyncTask.java:288) 
10-11 18:22:51.950 13604-5341/com.aaa.android.client W/System.err:  at java.util.concurrent.FutureTask.run(FutureTask.java:237) 
10-11 18:22:51.950 13604-5341/com.aaa.android.client W/System.err:  at android.os.AsyncTask$SerialExecutor$1.run(AsyncTask.java:231) 
10-11 18:22:51.950 13604-5341/com.aaa.android.client W/System.err:  at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1112) 
10-11 18:22:51.950 13604-5341/com.aaa.android.client W/System.err:  at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:587) 
10-11 18:22:51.950 13604-5341/com.aaa.android.client W/System.err:  at java.lang.Thread.run(Thread.java:818) 

Где проблема?

UPDATE: Я сделал много попыток на эту библиотеку, и я обнаружил это:

  • Если я сделать запрос на HTTPS: \ link.com OkHttp библиотеки автоматически доверие всех сертификатов.
  • Если я хочу доверять только моему сертификату, я должен сделать решение, которое я отправил .
  • Если я не хочу принимать все хосты, но без использования моего сертификата I может использовать имя хостаVerifier как предложение BNK.

Но почему я поставил вопрос, работает ли мое решение? Потому что я глуп, и я сделал запрос на свой vps url (vpsxxx.net/directory.php), а не в мой домен (mydomain.it/directory.php).

Очевидно, что сертификат SSL применяется к моему домену, а не к моим vps.

Я надеюсь, что это может быть полезно для кого-то.

P.S .: Извините за мой английский! : D

ответ

3

Предположим, что ваше серверное приложение размещено на серверной машине с сертификатом сервера, в котором, например, "Issued to": "localhost". Затем внутри метода verify вы можете проверить "localhost".

HostnameVerifier hostnameVerifier = new HostnameVerifier() { 
    @Override 
    public boolean verify(String hostname, SSLSession session) { 
     HostnameVerifier hv = 
      HttpsURLConnection.getDefaultHostnameVerifier(); 
     return hv.verify("localhost", session); 
    } 
}; 

Вы можете прочитать по следующим ссылкам:

  1. HostnameVerifier

    Он будет использоваться во время рукопожатия, если имя хоста URL не соответствует идентификации хоста партнёра.

  2. Common Problems with Hostname Verification

    Одной из причин этого может произойти из-за ошибки конфигурации сервера. Сервер сконфигурирован с сертификатом, который не имеет субъект или альтернативное имя поля, которые соответствуют серверу вы пытаюсь достичь ...

Затем, вы можете использовать имя хоста верификатор в вашем приложении, позвонив по телефону client.setHostnameVerifier(hostnameVerifier);. Надеюсь это поможет!

P/S: другое временное обходное решение return true; внутри verify способ, однако не рекомендуется.

+0

Прочтите мое обновление! Большое спасибо! – diegocom

Смежные вопросы