如何使用Jsoup通过HTTPS连接?

2022-09-01 14:55:38

它在HTTP上工作正常,但是当我尝试使用HTTPS源时,它会引发以下异常:

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)

以下是相关代码:

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

答案 1

如果你想以正确的方式做到这一点,和/或者你只需要处理一个网站,那么你基本上需要获取相关网站的SSL证书并将其导入到你的Java密钥存储中。这将导致一个 JKS 文件,在使用 Jsoup(或 )之前,您又将其设置为 SSL 信任存储。java.net.URLConnection

您可以从 Web 浏览器的存储中获取证书。假设你正在使用Firefox。

  1. 使用Firefox转到有问题的网站,这在你的情况下 https://web2.uconn.edu/driver/old/timepoints.php?stopid=10
  2. 在地址栏中,您会看到蓝色的“uconn.edu”(这表示有效的SSL证书)
  3. 单击它以获取详细信息,然后单击“更多信息”按钮。
  4. 在出现的安全对话框中,单击“查看证书”按钮。
  5. 在显示的证书面板中,转到“详细信息”选项卡。
  6. 单击证书层次结构中最深的项目,在本例中为“web2.uconn.edu”,最后单击“导出”按钮。

现在你有一个文件。web2.uconn.edu.crt

接下来,打开命令提示符,并使用以下命令将其导入 Java 密钥库(它是 JRE 的一部分):keytool

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

必须指向您刚刚下载的文件的位置。必须指向生成的文件的位置(您又要将其设置为 SSL 信任存储)。这是必需的,您可以输入所需的任何密码,只要它至少为6个字符。-file.crt-keystore.jks-storepass

现在,您有了一个文件。最后,您可以将其设置为 SSL 信任存储,然后再进行连接,如下所示:web2.uconn.edu.jks

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();
// ...

作为一种完全不同的选择,特别是当你需要处理多个站点(即你正在创建一个万维网爬虫)时,那么你也可以指示Jsoup(基本上)盲目信任所有SSL证书。另请参阅本答案最底部的“处理不可信或配置错误的HTTPS站点”一节:使用java.net.URLConnection触发和处理HTTP请求java.net.URLConnection


答案 2

在我的情况下,我需要做的就是在我的连接中添加.validateTLSCertificates(false)

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

我也不得不增加读取超时,但我认为这是无关紧要的