sun.security.provider.certpath.SunCertPathBuilderException: unable to find valid certification path to requested target

最近在搞一个爬虫的时候, 对方网站是https的. 用 HttpURLConnection/HttpsUrlConnection 连接的时候会报 SSLHandshakeException:

javax.net.ssl.SSLHandshakeException: sun.security.validator.ValidatorException: PKIX path building failed: sun.security.provider.certpath.SunCertPathBuilderException: unable to find valid certification path to requested target

简单来讲就是 SSL 证书的问题. 具体可以看这篇文章 cnblog – 解决Java调用Azure SDK证书错误javax.net.ssl.SSLHandshakeException. 里面提到了两种解决方案, 最理想的是修改 keystore 文件, 但是按文中方法试过还是不行. 只有使用第一种方案, 使用 Java 的 TrustManager 忽略所有的 SSL 请求的证书. 这种方法理论上那是相当不推荐的, 但是既然是写爬虫, 安全性是次要的, 因为我们的爬虫程序不会一直运行, 即使有中间人攻击的话, 我们也只是抓不到数据罢了.

具体代码:

// Create a trust manager that does not validate certificate chains
TrustManager[] trustAllCerts = new TrustManager[]{new X509TrustManager(){
    public X509Certificate[] getAcceptedIssuers(){return null;}
    public void checkClientTrusted(X509Certificate[] certs, String authType){}
    public void checkServerTrusted(X509Certificate[] certs, String authType){}
}};
// Install the all-trusting trust manager
try {
    SSLContext sc = SSLContext.getInstance("TLS");
    sc.init(null, trustAllCerts, new SecureRandom());
    HttpsURLConnection.setDefaultSSLSocketFactory(sc.getSocketFactory());
} catch (Exception e) {
    ;
}

把上面代码在所有 HTTP 请求之前执行一次即可.

修改 keystore 的方式会继续跟进, 毕竟上面的解决方案不太专业. 感兴趣可以参考:

Ignore self signed ssl cert using jersey client
Java client certificates over https ssl
Resolving javaxnetssl sslhandshakeexception sun security validator validatore
Article most common java keytool keystore commands
Retrieving Certificate Authorities using OpenSSL
Exporting Certificate Authorities (CAs) from a Website
How to Export Certificate from Chrome on a Mac?
Disable certificate validation in java ssl connections
How to solve javax net ssl sslhandshakeexception error
Path building failed and unable to find valid certification path

或者 “About Me” 中有我邮箱, 可联系.


Sorry, Comments are closed!