¿Cómo conectarse a través de HTTPS usando Jsoup?

Funciona bien a través de HTTP, pero cuando bash utilizar una fuente HTTPS arroja la siguiente excepción:

10-12 13:22:11.169: WARN/System.err(332): javax.net.ssl.SSLHandshakeException: java.security.cert.CertPathValidatorException: Trust anchor for certification path not found. 10-12 13:22:11.179: WARN/System.err(332): at org.apache.harmony.xnet.provider.jsse.OpenSSLSocketImpl.startHandshake(OpenSSLSocketImpl.java:477) 10-12 13:22:11.179: WARN/System.err(332): at org.apache.harmony.xnet.provider.jsse.OpenSSLSocketImpl.startHandshake(OpenSSLSocketImpl.java:328) 10-12 13:22:11.179: WARN/System.err(332): at org.apache.harmony.luni.internal.net.www.protocol.http.HttpConnection.setupSecureSocket(HttpConnection.java:185) 10-12 13:22:11.179: WARN/System.err(332): at org.apache.harmony.luni.internal.net.www.protocol.https.HttpsURLConnectionImpl$HttpsEngine.makeSslConnection(HttpsURLConnectionImpl.java:433) 10-12 13:22:11.189: WARN/System.err(332): at org.apache.harmony.luni.internal.net.www.protocol.https.HttpsURLConnectionImpl$HttpsEngine.makeConnection(HttpsURLConnectionImpl.java:378) 10-12 13:22:11.189: WARN/System.err(332): at org.apache.harmony.luni.internal.net.www.protocol.http.HttpURLConnectionImpl.connect(HttpURLConnectionImpl.java:205) 10-12 13:22:11.189: WARN/System.err(332): at org.apache.harmony.luni.internal.net.www.protocol.https.HttpsURLConnectionImpl.connect(HttpsURLConnectionImpl.java:152) 10-12 13:22:11.189: WARN/System.err(332): at org.jsoup.helper.HttpConnection$Response.execute(HttpConnection.java:377) 10-12 13:22:11.189: WARN/System.err(332): at org.jsoup.helper.HttpConnection$Response.execute(HttpConnection.java:364) 10-12 13:22:11.189: WARN/System.err(332): at org.jsoup.helper.HttpConnection.execute(HttpConnection.java:143) 

Aquí está el código relevante:

 try { doc = Jsoup.connect("https url here").get(); } catch (IOException e) { Log.e("sys","coudnt get the html"); e.printStackTrace(); } 

Si quiere hacerlo de la manera correcta, y / o necesita lidiar con un solo sitio, básicamente necesita obtener el certificado SSL del sitio en cuestión e importarlo en su almacén de claves Java. Esto dará como resultado un archivo JKS que a su vez establecerá como SSL Trust Store antes de usar Jsoup (o java.net.URLConnection ).

Puede tomar el certificado de la tienda de su navegador web. Supongamos que estás usando Firefox.

  1. Vaya al sitio web en cuestión usando Firefox, que está en su caso https://web2.uconn.edu/driver/old/timepoints.php?stopid=10
  2. A la izquierda en la barra de direcciones verá “uconn.edu” en azul (esto indica un certificado SSL válido)
  3. Haga clic en él para más detalles y luego haga clic en el botón Más información .
  4. En el diálogo de seguridad que aparece, haga clic en el botón Ver Certificado .
  5. En el panel de certificado que aparece, ve a la pestaña Detalles .
  6. Haga clic en el elemento más profundo de la jerarquía de certificados, que en este caso es “web2.uconn.edu” y finalmente haga clic en el botón Exportar .

Ahora tiene un archivo web2.uconn.edu.crt .

A continuación, abra el símbolo del sistema e impórtelo en el almacén de claves Java utilizando el comando keytool (es parte del JRE):

 keytool -import -v -file /path/to/web2.uconn.edu.crt -keystore /path/to/web2.uconn.edu.jks -storepass drowssap 

El -file debe señalar a la ubicación del archivo .crt que acaba de descargar. El -keystore debe señalar a la ubicación del archivo .jks generado (que a su vez desea establecer como almacén de confianza SSL). Se requiere -storepass , puede ingresar la contraseña que quiera siempre que tenga al menos 6 caracteres.

Ahora, tienes un archivo web2.uconn.edu.jks . Finalmente puede establecerlo como SSL trust store antes de conectarse de la siguiente manera:

 System.setProperty("javax.net.ssl.trustStore", "/path/to/web2.uconn.edu.jks"); Document document = Jsoup.connect("https://web2.uconn.edu/driver/old/timepoints.php?stopid=10").get(); // ... 

Como una alternativa completamente diferente, especialmente cuando necesita tratar con múltiples sitios (es decir, está creando un rastreador web mundial), también puede indicarle a Jsoup (básicamente, java.net.URLConnection ) que confíe ciegamente en todos los certificados SSL. Consulte también la sección “Cómo tratar con sitios HTTPS no confiables o mal configurados” en la parte inferior de esta respuesta: Cómo usar java.net.URLConnection para iniciar y gestionar solicitudes HTTP

Me tropecé con las respuestas aquí y en la pregunta vinculada en mi búsqueda y quiero agregar dos piezas de información, ya que la respuesta aceptada no se ajusta a mi escenario bastante similar, pero hay una solución adicional que se ajusta incluso en ese caso (cert y el nombre de host no coincide con los sistemas de prueba).

  1. Hay una solicitud github para agregar tal funcionalidad. Así que quizás pronto el problema se resuelva: https://github.com/jhy/jsoup/pull/343 edite: se resolvió la solicitud de Github y el método para desactivar la validación de certificados es: validateTLSCertificates (boolean validate)
  2. Basado en http://www.nakov.com/blog/2009/07/16/disable-certificate-validation-in-java-ssl-connections/ Encontré una solución que parece funcionar (al menos en mi escenario donde jsoup 1.7.3 se llama como parte de una tarea de experto). Lo envolví en un método disableSSLCertCheck() que llamo antes del primer Jsoup.connect ().

Antes de utilizar este método , debe estar realmente seguro de que comprende lo que hace allí; no consultar los certificados SSL es algo realmente estúpido. Utilice siempre certificados SSL correctos para sus servidores que estén firmados por una CA comúnmente aceptada. Si no puede pagar una CA comúnmente aceptada, utilice certificados SSL correctos, sin embargo, con la respuesta aceptada por @BalusC más arriba. Si no puede configurar los certificados SSL correctos (que nunca deberían ser el caso en entornos de producción) el siguiente método podría funcionar:

  private void disableSSLCertCheck() throws NoSuchAlgorithmException, KeyManagementException { // Create a trust manager that does not validate certificate chains TrustManager[] trustAllCerts = new TrustManager[] {new X509TrustManager() { public java.security.cert.X509Certificate[] getAcceptedIssuers() { return null; } public void checkClientTrusted(X509Certificate[] certs, String authType) { } public void checkServerTrusted(X509Certificate[] certs, String authType) { } } }; // Install the all-trusting trust manager SSLContext sc = SSLContext.getInstance("SSL"); sc.init(null, trustAllCerts, new java.security.SecureRandom()); HttpsURLConnection.setDefaultSSLSocketFactory(sc.getSocketFactory()); // Create all-trusting host name verifier HostnameVerifier allHostsValid = new HostnameVerifier() { public boolean verify(String hostname, SSLSession session) { return true; } }; // Install the all-trusting host verifier HttpsURLConnection.setDefaultHostnameVerifier(allHostsValid); } 

En mi caso, todo lo que tenía que hacer era agregar .validateTLSCertificates (falso) en mi conexión

 Document doc = Jsoup.connect(httpsURLAsString) .timeout(60000).validateTLSCertificates(false).get(); 

También tuve que boost el tiempo de espera de lectura, pero creo que esto es irrelevante

Tuve el mismo problema, pero tomé la ruta perezosa: dígale a su aplicación que ignore el certificado y continúe de todos modos.

Obtuve el código de aquí: ¿cómo uso una URL HTTPS local en Java?

Tendrás que importar estas clases para que funcione:

 import javax.net.ssl.HostnameVerifier; import javax.net.ssl.HttpsURLConnection; import javax.net.ssl.SSLContext; import javax.net.ssl.SSLSession; import javax.net.ssl.TrustManager; import javax.net.ssl.X509TrustManager; 

Simplemente ejecute ese método en alguna parte antes de tratar de establecer la conexión y listo, solo confía en el certificado pase lo que pase. Por supuesto, esto no sirve de nada si realmente quiere asegurarse de que el certificado sea real, pero bueno para monitorear sus propios sitios web internos, etc.

No soy un experto en este campo, pero me encontré con una excepción similar cuando bash conectarme a un sitio web a través de HTTPS utilizando las API de java.net. El navegador hace un gran trabajo para usted con respecto a los certificados SSL cuando visita un sitio usando HTTPS. Sin embargo, cuando se conecta manualmente a los sitios (usando las solicitudes HTTP manualmente), todo el trabajo aún debe realizarse. Ahora no sé exactamente qué es todo este trabajo, pero tiene que ver con descargar certificados y colocarlos donde Java pueda encontrarlos. Aquí hay un enlace que con suerte lo guiará en la dirección correcta.

http://confluence.atlassian.com/display/JIRA/Connecting+to+SSL+services

Estaba enfrentando el mismo problema con Jsoup, no pude conectarme y obtener el documento para las URL de https, pero cuando cambié mi versión de JDK de 1.7 a 1.8, el problema se resolvió.

Puede ayudarte 🙂

He tenido ese problema solo en el entorno de desarrollo. La solución para resolverlo fue simplemente agregar algunas banderas para ignorar SSL a VM:

 -Ddeployment.security.TLSv1.1=false -Ddeployment.security.TLSv1.2=false 

Intenta seguir (simplemente ponlo antes de Jsoup.connect("https://example.com") :

  Authenticator.setDefault(new Authenticator() { @Override protected PasswordAuthentication getPasswordAuthentication() { return new PasswordAuthentication(username, password.toCharArray()); } });