如何使用Jsoup通过HTTPS进行连接?

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

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(); } 

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

你可以从你的浏览器的商店拿到证书。 假设您使用的是Firefox。

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

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

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

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

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

现在,你有一个web2.uconn.edu.jks文件。 您可以在连接之前最终将其设置为SSL信任存储,如下所示:

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

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

我在这里和在我的search链接的问题偶然find答案,并希望添加两个信息,因为接受的答案不适合我非常类似的情况,但有一个额外的解决scheme,即使在这种情况下适合(证书和主机名称不匹配testing系统)。

  1. 有一个github请求添加这样的function。 所以也许很快这个问题就解决了: https : //github.com/jhy/jsoup/pull/343编辑:Github的请求已经解决,禁用证书validation的方法是:validateTLSCertificates(boolean validate)
  2. 基于http://www.nakov.com/blog/2009/07/16/disable-certificate-validation-in-java-ssl-connections/我发现了一个似乎工作的解决scheme(至less在我的情况下,jsoup 1.7.3被称为maven任务的一部分)。 我把它封装在方法disableSSLCertCheck() ,我在第一个Jsoup.connect()之前调用它。

在使用这个方法之前 ,你应该确定你明白你在那里做什么 – 不检查SSL证书是一件非常愚蠢的事情。 对于由普遍接受的CA签署的服务器,始终使用正确的SSL证书。 如果您无法承受普遍接受的CA,则使用正确的SSL证书,但是@BalusC接受上述答案。 如果您无法configuration正确的SSL证书(在生产环境中永远不会这样),可以使用以下方法:

  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); } 

我有同样的问题,但采取了懒惰的路线 – 告诉你的应用程序忽略证书,并继续进行。

我从这里得到了代码: 如何在java中使用本地HTTPS URL?

你将不得不导入这些类来使其工作:

 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; 

在尝试build立连接之前,只要在某个地方运行该方法,那么无论如何,只要相信证书即可。 当然,如果你真的想要确保证书是真实的,但是对于监控你自己的内部网站是非常有用的。

我不是这个领域的专家,但当我尝试使用java.net API通过HTTPS连接到一个网站时遇到了类似的exception。 当您使用HTTPS访问网站时,浏览器会为您提供有关SSL证书的大量工作。 但是,当您手动连接到网站(手动使用HTTP请求)时,仍然需要完成所有工作。 现在我不知道这些工作究竟是什么,但是它需要下载证书并将其放在Java可以find的地方。 这里有一个链接,希望你指向正确的方向。

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

尝试下面(只要把它放在Jsoup.connect("https://example.com")

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