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


Funciona bien a través de HTTP, pero cuando intento 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();
}

18
2017-10-12 17:29


origen


Respuestas:


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 almacén de confianza SSL 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 Más información botón.
  4. En el diálogo de seguridad que aparece, haga clic en Ver Certificado botón.
  5. En el panel de certificado que aparece, vaya al Detalles lengüeta.
  6. Haga clic en el elemento más profundo de la jerarquía del certificado, que en este caso es "web2.uconn.edu" y finalmente haga clic en Exportar botón.

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

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

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

los -file debe señalar a la ubicación de la .crt archivo que acaba de descargar. los -keystore debe señalar a la ubicación de la generada .jks archivo (que a su vez desea configurar como SSL trust store). los -storepass es obligatorio, solo puede ingresar la contraseña que quiera, siempre que tenga al menos 6 caracteres.

Ahora, tienes un web2.uconn.edu.jks archivo. 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 instruir a Jsoup (básicamente, java.net.URLConnection) confiar ciegamente en todos los certificados SSL. Consulte también la sección "Cómo tratar con sitios HTTPS desconfiados o que no son de confianza" en la parte inferior de esta respuesta: Usando java.net.URLConnection para disparar y manejar solicitudes HTTP


46
2017-10-12 19:49



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. Entonces, quizás pronto el problema será resuelto: https://github.com/jhy/jsoup/pull/343  editar: la solicitud Github se resolvió y el método para desactivar la validación del certificado es: validateTLSCertificates (boolean validate)
  2. Residencia 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 se llama a jsoup 1.7.3 como parte de una tarea de experto). Lo envolví en un método disableSSLCertCheck() que llamo antes de la primera Jsoup.connect ().

Antes de usar este método, deberías estar realmente seguro de que entiendes lo que haces allí, no verificando 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);
    }

7
2017-07-30 12:12



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 aumentar el tiempo de espera de lectura, pero creo que esto es irrelevante


4
2018-01-16 09:40



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.


2
2018-05-09 03:56



No soy un experto en este campo, pero me encontré con una excepción similar cuando intento 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


0
2017-10-12 17:43



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 :)


0
2018-02-22 14:11



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

0
2017-08-04 08:42



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

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

-3
2017-12-11 10:36