使用jsoup遇到javax.net.ssl.SSLHandshakeException: sun.security.validator.ValidatorException异常解决方法

引言

在开发过程中,我们经常会使用jsoup这个Java库来解析和操作HTML。然而,在使用jsoup的过程中,有时候会遇到"javax.net.ssl.SSLHandshakeException: sun.security.validator.ValidatorException"这个异常。这个异常通常是由于与服务器建立SSL连接时出现问题导致的。本文将帮助你了解这个异常的原因,并提供解决方法。

异常原因解析

在使用jsoup进行网络请求时,如果请求的网站使用了SSL证书加密,那么在和服务器建立SSL连接时,需要对服务器的证书进行验证。这个异常的原因是由于jsoup默认使用了Java的证书验证机制,而某些网站的证书无法通过Java的证书验证机制的验证而导致的。

解决方法

为了解决这个问题,我们需要自定义一个SSL验证器,来实现对网站证书的验证。下面是解决这个问题的步骤:

st=>start: 开始
op1=>operation: 创建一个TrustManager数组
op2=>operation: 实现X509TrustManager接口的方法
op3=>operation: 创建一个SSLContext,使用自定义的TrustManager
op4=>operation: 设置Jsoup的SSLContext
e=>end: 结束

st->op1->op2->op3->op4->e

步骤说明

  1. 创建一个TrustManager数组:我们需要创建一个实现X509TrustManager接口的TrustManager数组,来实现对证书的验证。TrustManager是JSSE(Java Secure Socket Extension)框架中的一个类,用于证书链的验证。
  2. 实现X509TrustManager接口的方法:在TrustManager数组中,我们需要实现X509TrustManager接口的三个方法:checkClientTrusted,checkServerTrusted和getAcceptedIssuers。这些方法定义了如何验证证书。
  3. 创建一个SSLContext,使用自定义的TrustManager:SSLContext是Java加密通信的框架,我们需要使用自定义的TrustManager来创建一个SSLContext对象。
  4. 设置Jsoup的SSLContext:最后,我们需要将自定义的SSLContext对象设置到Jsoup中,使其使用我们自定义的SSLContext来进行网络请求。

代码实现

下面是每一步所需要做的事情以及相应的代码:

第一步:创建一个TrustManager数组
TrustManager[] trustAllCerts = new TrustManager[]{
    new X509TrustManager() {
        public java.security.cert.X509Certificate[] getAcceptedIssuers() {
            return null;
        }

        public void checkClientTrusted(
            java.security.cert.X509Certificate[] certs, String authType) {
        }

        public void checkServerTrusted(
            java.security.cert.X509Certificate[] certs, String authType) {
        }
    }
};

在这里,我们创建了一个包含一个匿名内部类的TrustManager数组。在这个匿名内部类中,我们实现了X509TrustManager接口的三个方法:getAcceptedIssuers,checkClientTrusted和checkServerTrusted。其中,getAcceptedIssuers方法返回null,表示不验证任何证书;checkClientTrusted和checkServerTrusted方法为空,表示不验证任何客户端和服务器端的证书。

第二步:实现X509TrustManager接口的方法

这一步在第一步的代码中已经完成了。

第三步:创建一个SSLContext,使用自定义的TrustManager
SSLContext sslContext = SSLContext.getInstance("SSL");
sslContext.init(null, trustAllCerts, new java.security.SecureRandom());

在这里,我们通过SSLContext类的getInstance方法来获取一个“SSL”类型的SSLContext对象。然后,我们使用init方法来初始化SSLContext对象,第一个参数为KeyManager数组(null表示不需要KeyManager),第二个参数为TrustManager数组(使用我们自定义的TrustManager),第三个参数为随机数生成器。

第四步:设置Jsoup的SSLContext
Jsoup.connect(url).sslSocketFactory(sslContext.getSocketFactory()).get();

在这里,我们使用Jsoup的connect方法来发起一个网络请求,并通过sslSocketFactory方法将我们自定义的SSLContext的SocketFactory设置为Jsoup的SSLContext。

完整代码示例

import org.jsoup.Jsoup;
import