Recientemente publiqué una pregunta sobre el HttpClient
Https (que se encuentra aquí ). He avanzado un poco, pero me he encontrado con nuevos problemas. Al igual que con mi último problema, parece que no puedo encontrar un ejemplo en ningún lugar que me funcione. Básicamente, quiero que mi cliente acepte cualquier certificado (porque solo estoy apuntando a un servidor) pero sigo obteniendo unjavax.net.ssl.SSLException: Not trusted server certificate exception.
Entonces esto es lo que tengo:
public void connect() throws A_WHOLE_BUNCH_OF_EXCEPTIONS {
HttpPost post = new HttpPost(new URI(PROD_URL));
post.setEntity(new StringEntity(BODY));
KeyStore trusted = KeyStore.getInstance("BKS");
trusted.load(null, "".toCharArray());
SSLSocketFactory sslf = new SSLSocketFactory(trusted);
sslf.setHostnameVerifier(SSLSocketFactory.ALLOW_ALL_HOSTNAME_VERIFIER);
SchemeRegistry schemeRegistry = new SchemeRegistry();
schemeRegistry.register(new Scheme ("https", sslf, 443));
SingleClientConnManager cm = new SingleClientConnManager(post.getParams(),
schemeRegistry);
HttpClient client = new DefaultHttpClient(cm, post.getParams());
HttpResponse result = client.execute(post);
}
Y aquí está el error que obtengo:
W/System.err( 901): javax.net.ssl.SSLException: Not trusted server certificate
W/System.err( 901): at org.apache.harmony.xnet.provider.jsse.OpenSSLSocketImpl.startHandshake(OpenSSLSocketImpl.java:360)
W/System.err( 901): at org.apache.http.conn.ssl.AbstractVerifier.verify(AbstractVerifier.java:92)
W/System.err( 901): at org.apache.http.conn.ssl.SSLSocketFactory.connectSocket(SSLSocketFactory.java:321)
W/System.err( 901): at org.apache.http.impl.conn.DefaultClientConnectionOperator.openConnection(DefaultClientConnectionOperator.java:129)
W/System.err( 901): at org.apache.http.impl.conn.AbstractPoolEntry.open(AbstractPoolEntry.java:164)
W/System.err( 901): at org.apache.http.impl.conn.AbstractPooledConnAdapter.open(AbstractPooledConnAdapter.java:119)
W/System.err( 901): at org.apache.http.impl.client.DefaultRequestDirector.execute(DefaultRequestDirector.java:348)
W/System.err( 901): at org.apache.http.impl.client.AbstractHttpClient.execute(AbstractHttpClient.java:555)
W/System.err( 901): at org.apache.http.impl.client.AbstractHttpClient.execute(AbstractHttpClient.java:487)
W/System.err( 901): at org.apache.http.impl.client.AbstractHttpClient.execute(AbstractHttpClient.java:465)
W/System.err( 901): at me.harrisonlee.test.ssl.MainActivity.connect(MainActivity.java:129)
W/System.err( 901): at me.harrisonlee.test.ssl.MainActivity.access$0(MainActivity.java:77)
W/System.err( 901): at me.harrisonlee.test.ssl.MainActivity$2.run(MainActivity.java:49)
W/System.err( 901): Caused by: java.security.cert.CertificateException: java.security.InvalidAlgorithmParameterException: the trust anchors set is empty
W/System.err( 901): at org.apache.harmony.xnet.provider.jsse.TrustManagerImpl.checkServerTrusted(TrustManagerImpl.java:157)
W/System.err( 901): at org.apache.harmony.xnet.provider.jsse.OpenSSLSocketImpl.startHandshake(OpenSSLSocketImpl.java:355)
W/System.err( 901): ... 12 more
W/System.err( 901): Caused by: java.security.InvalidAlgorithmParameterException: the trust anchors set is empty
W/System.err( 901): at java.security.cert.PKIXParameters.checkTrustAnchors(PKIXParameters.java:645)
W/System.err( 901): at java.security.cert.PKIXParameters.<init>(PKIXParameters.java:89)
W/System.err( 901): at org.apache.harmony.xnet.provider.jsse.TrustManagerImpl.<init>(TrustManagerImpl.java:89)
W/System.err( 901): at org.apache.harmony.xnet.provider.jsse.TrustManagerFactoryImpl.engineGetTrustManagers(TrustManagerFactoryImpl.java:134)
W/System.err( 901): at javax.net.ssl.TrustManagerFactory.getTrustManagers(TrustManagerFactory.java:226)W/System.err( 901): at org.apache.http.conn.ssl.SSLSocketFactory.createTrustManagers(SSLSocketFactory.java:263)
W/System.err( 901): at org.apache.http.conn.ssl.SSLSocketFactory.<init>(SSLSocketFactory.java:190)
W/System.err( 901): at org.apache.http.conn.ssl.SSLSocketFactory.<init>(SSLSocketFactory.java:216)
W/System.err( 901): at me.harrisonlee.test.ssl.MainActivity.connect(MainActivity.java:107)
W/System.err( 901): ... 2 more
java
ssl
https
certificate
apache-httpclient-4.x
harrisonlee
fuente
fuente
Respuestas:
Nota: No implemente esto en el código de producción que usará en una red en la que no confía por completo. Especialmente todo lo que pasa por internet público.
Tu pregunta es justo lo que quiero saber. Después de hacer algunas búsquedas, la conclusión es la siguiente.
En la forma HttpClient, debe crear una clase personalizada desde org.apache.http.conn.ssl.SSLSocketFactory, no la org.apache.http.conn.ssl.SSLSocketFactory en sí. Se pueden encontrar algunas pistas en esta publicación El manejo personalizado de SSL dejó de funcionar en Android 2.2 FroYo .
Un ejemplo es como ...
y use esta clase mientras crea una instancia de HttpClient.
Por cierto, el siguiente enlace es para alguien que está buscando la solución HttpURLConnection. Https Connection Android
He probado los dos tipos de soluciones anteriores en froyo, y todos funcionan de maravilla en mis casos. Finalmente, usar HttpURLConnection puede enfrentar los problemas de redireccionamiento, pero esto va más allá del tema.
Nota: Antes de decidirse a confiar en todos los certificados, probablemente debería conocer bien el sitio y no será perjudicial para el usuario final.
De hecho, el riesgo que corres debe considerarse con cuidado, incluido el efecto del sitio simulado del hacker mencionado en los siguientes comentarios que aprecio profundamente. En alguna situación, aunque puede ser difícil cuidar todos los certificados, es mejor que conozca los inconvenientes implícitos para confiar en todos ellos.
fuente
getAcceptedIssuers()
no está permitido devolver nulo.Básicamente, tiene cuatro posibles soluciones para solucionar una excepción "No confiable" en Android usando httpclient:
Esta respuesta utiliza la solución n. ° 4, que me parece la más sólida.
La solución es utilizar un SSLSocketFactory que puede aceptar múltiples KeyStores, lo que le permite suministrar su propio KeyStore con sus propios certificados. Esto le permite cargar certificados adicionales de nivel superior como Thawte que pueden faltar en algunos dispositivos Android. También le permite cargar sus propios certificados autofirmados también. Primero utilizará los certificados de dispositivo predeterminados integrados y recurrirá a sus certificados adicionales solo cuando sea necesario.
Primero, querrás determinar qué certificado te falta en tu KeyStore. Ejecute el siguiente comando:
Y verá resultados como el siguiente:
Como puede ver, nuestro certificado raíz es de Thawte. Vaya al sitio web de su proveedor y busque el certificado correspondiente. Para nosotros, fue aquí , y se puede ver que el que necesitábamos era el Copyright 2006.
Si está utilizando un certificado autofirmado, no es necesario que realice el paso anterior ya que ya tiene su certificado de firma.
Luego, cree un archivo de almacén de claves que contenga el certificado de firma faltante. Crazybob tiene detalles sobre cómo hacer esto en Android , pero la idea es hacer lo siguiente:
Si aún no lo tiene, descargue la biblioteca del proveedor del castillo hinchable de: http://www.bouncycastle.org/latest_releases.html . Esto irá en tu classpath a continuación.
Ejecute un comando para extraer el certificado del servidor y crear un archivo pem. En este caso, mycert.pem.
Luego ejecute los siguientes comandos para crear el almacén de claves.
Notarás que el script anterior coloca el resultado en
res/raw/mystore.bks
. Ahora tiene un archivo que cargará en su aplicación de Android que proporciona los certificados faltantes.Para hacer esto, registre su SSLSocketFactory para el esquema SSL:
Para crear su SSLSocketFactory:
Y finalmente, el código AdditionalKeyStoresSSLSocketFactory, que acepta su nuevo KeyStore y comprueba si el KeyStore incorporado no puede validar un certificado SSL:
fuente
http://stackoverflow.com/questions/7822381/need-help-understanding-certificate-chains
Agregue este código antes del
HttpsURLConnection
y se hará. Lo tengo.Espero que esto te ayude.
fuente
Esta es una mala idea. Confiar en cualquier certificado es solo (muy) ligeramente mejor que no usar SSL en absoluto. Cuando dice "Quiero que mi cliente acepte cualquier certificado (porque solo estoy señalando a un servidor)" está asumiendo que esto significa que de alguna manera señalar a "un servidor" es seguro, lo cual no está en una red pública.
Estás completamente abierto a un ataque de hombre en el medio al confiar en cualquier certificado. Cualquier persona puede usar su conexión proxy mediante el establecimiento de una conexión SSL separada con usted y con el servidor final. El MITM tiene acceso a toda su solicitud y respuesta. A menos que realmente no necesite SSL en primer lugar (su mensaje no tiene nada sensible y no hace autenticación), no debe confiar en todos los certificados a ciegas.
Debería considerar agregar el certificado público a un jks usando keytool y usarlo para construir su fábrica de sockets, como este:
Esto tiene una advertencia a tener en cuenta. El certificado caducará eventualmente y el código dejará de funcionar en ese momento. Puede determinar fácilmente cuándo ocurrirá esto mirando el certificado.
fuente
null
enSSLContext.init). You should also use the default algorithms (KMF/TMF.getDefaultAlgorithm() ), instead of hard-coding
SunX509` (más aún porque el valor predeterminado para TMF está realmentePKIX
en Sun / Oracle JVM).myjks.jks
viene?Puede deshabilitar la verificación HttpURLConnection SSL para fines de prueba de esta manera desde la API 8:
fuente
org.apache.http.conn.ssl.AllowAllHostnameVerifier
es obsoleto.AllowAllHostnameVerifier
se reemplaza porNoopHostnameVerifier
"La API de HttpComponents ha cambiado. Funciona con el siguiente código.
fuente
El código anterior en https://stackoverflow.com/a/6378872/1553004 es correcto, excepto que también DEBE llamar al verificador de nombre de host:
Me inscribí en stackoverflow expresamente para agregar esta solución. ¡Presta atención a mi advertencia!
fuente
Estoy agregando una respuesta para aquellos que usan httpclient-4.5, y probablemente también funcione para 4.4.
fuente
Confiar en todos los certificados no era una alternativa real para mí, así que hice lo siguiente para que HttpsURLConnection confiara en un nuevo certificado (consulte también http://nelenkov.blogspot.jp/2011/12/using-custom-certificate-trust-store- on.html ).
Obtener el certificado; Logré esto exportando el certificado en Firefox (haga clic en el pequeño ícono de candado, obtenga los detalles del certificado, haga clic en exportar), luego usé portecle para exportar un almacén de confianza (BKS).
Cargue el Truststore de /res/raw/geotrust_cert.bks con el siguiente código:
fuente
IOExceptionjavax.net.ssl.SSLPeerUnverifiedException: No peer certificate
. Esto cuando se realiza la llamada de ejecución real en el HttpClient después de que se realiza la configuración anterior.Aquí hay una versión mucho más simple que usa el código de cliente http 4.1.2. Esto se puede modificar a cualquier algoritmo de confianza que considere adecuado.
fuente
Recibí una respuesta de "emmby" (respondió el 16 de junio de 11 a las 21:29), elemento n. ° 4: "Cree un SSLSocketFactory personalizado que use el certificado integrado KeyStore, pero recurra a un KeyStore alternativo para cualquier cosa que falle para verificar con el valor predeterminado ".
Esta es una implementación simplificada. Cargue el almacén de claves del sistema y fusione con el almacén de claves de la aplicación.
Un modo simple para convertir de JKS a BKS:
* Nota: en Android 4.0 (ICS) la Trust Store ha cambiado, más información: http://nelenkov.blogspot.com.es/2011/12/ics-trust-store-implementation.html
fuente
Para aquellos que desean permitir que todos los certificados funcionen (con fines de prueba) sobre OAuth, siga estos pasos:
1) Descargue el código fuente de la API de Android OAuth aquí: https://github.com/kaeppler/signpost
2) Busque el archivo "CommonsHttpOAuthProvider" clase
3) Cámbielo de la siguiente manera:
El "MySSLSocketFactory" anterior se basa en la respuesta aceptada. Para hacerlo aún más fácil, aquí va la clase completa:
}
Espero que esto ayude a alguien.
fuente
HttpClient
y HTTPS; no OAuth para Android de un proyecto GitHub.Usé esto y funciona para mí en todos los sistemas operativos.
fuente
Simplemente agregar
-Dtrust_all_cert=true
a los argumentos de VM debería ser suficiente. Este argumento le dice a Java que ignore las comprobaciones de certificados.fuente
Cualquier persona que todavía tenga problemas con los Certificados SSL de StartCom en Android 2.1 visite https://www.startssl.com/certs/ y descargue ca.pem, ahora en la respuesta proporcionada por @emmby replace
con
Debería funcionar fuera de la caja. Estuve luchando por más de un día, incluso después de una respuesta perfecta de @emmby ... Espero que esto ayude a alguien ...
fuente
usa esta clase
}
fuente
ingrese la descripción de la imagen aquí
Un sspi falló en xamarin android.
Encontré esta solución; ponga este código antes de presionar un enlace HTTPS
fuente
trabajar con todos los https
fuente
Hay muchas respuestas anteriores, pero no pude hacer que ninguna de ellas funcionara correctamente (con mi tiempo limitado), por lo que para cualquier otra persona en la misma situación, puede probar el siguiente código que funcionó perfectamente para mis propósitos de prueba de Java:
y llama como:
Referencia: http://tech.chitgoks.com/2011/04/24/how-to-avoid-javax-net-ssl-sslpeerunverifiedexception-peer-not-authenticated-problem-using-apache-httpclient/
fuente
Simplemente use esto:
fuente
La respuesta de Daniel fue buena, excepto que tuve que cambiar este código ...
a este código ...
para que funcione.
fuente