OkHttp certificado de confianza
En mi aplicación android necesito ejecutar alguna solicitud a mi servidor con la biblioteca OkHttp. Tengo un certificado del ssl que consiste en cuatro porciones:
- AddTrustExternalCARoot.crt
- COMODORSAAddTrustCA.crt
- COMODORESADomainValidationSecureServerCA.crt
- Www_mydomain_com.crt
He importado todas las partes en el portecle 1.9, después fijé mi contraseña del keystore y he exportado el CERT de .bks.
- Soporte de TLS v1.2 en Webview Android
- El servidor no admite la suite de cifrado predeterminada de Android 5.0
- ¿Por qué android obtiene el certificado ssl incorrecto? (Dos dominios, un servidor)
- HTTPS con Retrofit y OkHttp Handshake falló
- Certificado de fijación en Android
Entonces he insertado mycert.bks en la carpeta res / raw de mi proyecto de aplicación. Ahora estoy intentando conectarme a mi servidor por https con este código:
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; }
Pero obtengo una excepción, este es el 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)
¿Dónde está el problema?
ACTUALIZACIÓN: He hecho muchos intentos en esta biblioteca y descubrí esto:
- Si hago una solicitud a la biblioteca https: \ link.com OkHttp confía automáticamente en todo el certificado.
- Si quiero confiar sólo en mi certificado, tengo que hacer la solución que he publicado anteriormente.
- Si no quiero aceptar todo el host, pero sin usar mi certificado puedo usar hostnameVerifier como sugerir BNK.
¿Pero por qué publiqué la pregunta si mi solución funciona? Porque soy estúpido y hice la solicitud a mi url de vps (vpsxxx.net/directory.php) y no a mi dominio (mydomain.it/directory.php).
Obviamente el certificado SSL se aplica a mi dominio y no a mis vps.
Espero que esto pueda ser útil para alguien.
PS: Lo siento por mi Inglés! :RE
- Deshabilitar SSL como un protocolo en HttpsURLConnection
- Cómo deshabilitar SSLbackbackback con okhttp
- Comodo SSL: ERR_CERT_AUTHORITY_INVALID en Chrome móvil y Opera móvil (Android)
- Pinzado de certificado SSL con Picasso
- Error de certificado de cliente con Jelly beans
- La autenticación mutua de SSL FAIL en Android Client acepta el certificado de servidores pero el servidor no obtiene el certificado de cliente
- WebView con https loadUrl muestra la página en blanco
- Certificado de Cliente de Webview de Android, Autenticación Mutua, SSL sobre Webview
Supongamos que su aplicación de servidor se aloja dentro de una máquina servidor que tiene un certificado de servidor en el que "Issued to"
es "localhost"
, por ejemplo. Entonces, dentro del método de verify
se puede verificar "localhost"
.
HostnameVerifier hostnameVerifier = new HostnameVerifier() { @Override public boolean verify(String hostname, SSLSession session) { HostnameVerifier hv = HttpsURLConnection.getDefaultHostnameVerifier(); return hv.verify("localhost", session); } };
Puede leer más en los siguientes enlaces:
-
HostnameVerifier
Se debe utilizar durante un apretón de manos si el nombre de host de la URL no coincide con el nombre de host de identificación de los pares.
-
Problemas comunes con la verificación de nombre de host
Una razón por la que esto puede suceder se debe a un error de configuración del servidor. El servidor está configurado con un certificado que no tiene un tema o sujetar campos de nombres alternativos que coincidan con el servidor al que está intentando llegar …
A continuación, puede utilizar el verificador de nombre de host en su aplicación, llamando a client.setHostnameVerifier(hostnameVerifier);
. ¡Espero que esto ayude!
P / S: otra solución temporal es return true;
Dentro de verify
método, sin embargo, no es recomendable.
- SocketTimeoutException actualización de Android
- IllegalStateException al grabar un video en una tarjeta SD externa con el nuevo Storage Access Framework (SAF)