【JAVA】PKIX path building failed: unable to find valid certification path to requested target关闭SSL

解决:创建OkHttpClient时禁用SSL验证

调用示例

package com.lct.webCollector.xhrrj;

import cn.edu.hfut.dmic.webcollector.model.CrawlDatums;
import cn.edu.hfut.dmic.webcollector.model.Page;
import cn.edu.hfut.dmic.webcollector.plugin.net.OkHttpRequesterSSLIgnore;
import cn.edu.hfut.dmic.webcollector.plugin.ram.RamCrawler;

public class CustomSSLRamCrawler extends RamCrawler {
    public static void main(String[] args) throws Exception {
        CustomSSLRamCrawler crawler = new CustomSSLRamCrawler();
        crawler.setRequester(new OkHttpRequesterSSLIgnore());
        crawler.addSeed("https://lexji.com");
        crawler.start(1);
    }

    @Override
    public void visit(Page page, CrawlDatums crawlDatums) {
        // 处理页面内容
        String url = page.url();
        String html = page.html();
        System.out.println("URL: " + url);
        System.out.println("HTML长度: " + html.length());
    }
}

在这里插入图片描述

package cn.edu.hfut.dmic.webcollector.plugin.net;

import okhttp3.OkHttpClient;

import javax.net.ssl.SSLContext;
import javax.net.ssl.SSLSocketFactory;
import javax.net.ssl.TrustManager;
import javax.net.ssl.X509TrustManager;
import java.security.KeyManagementException;
import java.security.NoSuchAlgorithmException;
import java.security.cert.CertificateException;
import java.util.concurrent.TimeUnit;

public class OkHttpRequesterSSLIgnore extends OkHttpRequester{
    public OkHttpRequesterSSLIgnore(){
        super();
        try {
            // 创建信任所有证书的TrustManager
            final TrustManager[] trustAllCerts = new TrustManager[] {
                    new X509TrustManager() {
                        @Override
                        public void checkClientTrusted(java.security.cert.X509Certificate[] chain, String authType) throws CertificateException {
                        }

                        @Override
                        public void checkServerTrusted(java.security.cert.X509Certificate[] chain, String authType) throws CertificateException {
                        }

                        @Override
                        public java.security.cert.X509Certificate[] getAcceptedIssuers() {
                            return new java.security.cert.X509Certificate[]{};
                        }
                    }
            };

            // 创建SSL上下文并配置
            final SSLContext sslContext = SSLContext.getInstance("SSL");
            sslContext.init(null, trustAllCerts, new java.security.SecureRandom());
            final SSLSocketFactory sslSocketFactory = sslContext.getSocketFactory();

            // 创建OkHttpClient并配置
             client = new OkHttpClient.Builder()
                    .connectTimeout(30, TimeUnit.SECONDS)
                    .readTimeout(30, TimeUnit.SECONDS)
                    .writeTimeout(30, TimeUnit.SECONDS)
                    .sslSocketFactory(sslSocketFactory, (X509TrustManager)trustAllCerts[0])
                    .hostnameVerifier((hostname, session) -> true) // 关闭主机名验证
                    .build();

        } catch (NoSuchAlgorithmException | KeyManagementException e) {
            throw new RuntimeException(e);
        }
    }
}

用webcollector爬取有些网站时,找不到有效的证书路径?

java 怎么解决“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
at sun.security.ssl.Alerts.getSSLException(Alerts.java:192)
at sun.security.ssl.SSLSocketImpl.fatal(SSLSocketImpl.java:1949)
at sun.security.ssl.Handshaker.fatalSE(Handshaker.java:302)
at sun.security.ssl.Handshaker.fatalSE(Handshaker.java:296)
at sun.security.ssl.ClientHandshaker.serverCertificate(ClientHandshaker.java:1497)
at sun.security.ssl.ClientHandshaker.processMessage(ClientHandshaker.java:212)
at sun.security.ssl.Handshaker.processLoop(Handshaker.java:979)
at sun.security.ssl.Handshaker.process_record(Handshaker.java:914)
at sun.security.ssl.SSLSocketImpl.readRecord(SSLSocketImpl.java:1062)
at sun.security.ssl.SSLSocketImpl.performInitialHandshake(SSLSocketImpl.java:1375)
at sun.security.ssl.SSLSocketImpl.startHandshake(SSLSocketImpl.java:1403)
at sun.security.ssl.SSLSocketImpl.startHandshake(SSLSocketImpl.java:1387)
at okhttp3.internal.connection.RealConnection.connectTls(RealConnection.kt:379)
at okhttp3.internal.connection.RealConnection.establishProtocol(RealConnection.kt:337)
at okhttp3.internal.connection.RealConnection.connect(RealConnection.kt:209)
at okhttp3.internal.connection.ExchangeFinder.findConnection(ExchangeFinder.kt:226)
at okhttp3.internal.connection.ExchangeFinder.findHealthyConnection(ExchangeFinder.kt:106)
at okhttp3.internal.connection.ExchangeFinder.find(ExchangeFinder.kt:74)
at okhttp3.internal.connection.RealCall.initExchangeokhttp(RealCall.kt:255)atokhttp3.internal.connection.ConnectInterceptor.intercept(ConnectInterceptor.kt:32)atokhttp3.internal.http.RealInterceptorChain.proceed(RealInterceptorChain.kt:109)atokhttp3.internal.cache.CacheInterceptor.intercept(CacheInterceptor.kt:95)atokhttp3.internal.http.RealInterceptorChain.proceed(RealInterceptorChain.kt:109)atokhttp3.internal.http.BridgeInterceptor.intercept(BridgeInterceptor.kt:83)atokhttp3.internal.http.RealInterceptorChain.proceed(RealInterceptorChain.kt:109)atokhttp3.internal.http.RetryAndFollowUpInterceptor.intercept(RetryAndFollowUpInterceptor.kt:76)atokhttp3.internal.http.RealInterceptorChain.proceed(RealInterceptorChain.kt:109)atokhttp3.internal.connection.RealCall.getResponseWithInterceptorChainokhttp(RealCall.kt:255) at okhttp3.internal.connection.ConnectInterceptor.intercept(ConnectInterceptor.kt:32) at okhttp3.internal.http.RealInterceptorChain.proceed(RealInterceptorChain.kt:109) at okhttp3.internal.cache.CacheInterceptor.intercept(CacheInterceptor.kt:95) at okhttp3.internal.http.RealInterceptorChain.proceed(RealInterceptorChain.kt:109) at okhttp3.internal.http.BridgeInterceptor.intercept(BridgeInterceptor.kt:83) at okhttp3.internal.http.RealInterceptorChain.proceed(RealInterceptorChain.kt:109) at okhttp3.internal.http.RetryAndFollowUpInterceptor.intercept(RetryAndFollowUpInterceptor.kt:76) at okhttp3.internal.http.RealInterceptorChain.proceed(RealInterceptorChain.kt:109) at okhttp3.internal.connection.RealCall.getResponseWithInterceptorChainokhttp(RealCall.kt:255)atokhttp3.internal.connection.ConnectInterceptor.intercept(ConnectInterceptor.kt:32)atokhttp3.internal.http.RealInterceptorChain.proceed(RealInterceptorChain.kt:109)atokhttp3.internal.cache.CacheInterceptor.intercept(CacheInterceptor.kt:95)atokhttp3.internal.http.RealInterceptorChain.proceed(RealInterceptorChain.kt:109)atokhttp3.internal.http.BridgeInterceptor.intercept(BridgeInterceptor.kt:83)atokhttp3.internal.http.RealInterceptorChain.proceed(RealInterceptorChain.kt:109)atokhttp3.internal.http.RetryAndFollowUpInterceptor.intercept(RetryAndFollowUpInterceptor.kt:76)atokhttp3.internal.http.RealInterceptorChain.proceed(RealInterceptorChain.kt:109)atokhttp3.internal.connection.RealCall.getResponseWithInterceptorChainokhttp(RealCall.kt:201)
at okhttp3.internal.connection.RealCall.execute(RealCall.kt:154)
at cn.edu.hfut.dmic.webcollector.plugin.net.OkHttpRequester.getResponse(OkHttpRequester.java:94)
at cn.edu.hfut.dmic.webcollector.crawler.AutoParseCrawler.execute(AutoParseCrawler.java:87)
at cn.edu.hfut.dmic.webcollector.fetcher.Fetcher$FetcherThread.run(Fetcher.java:245)
Caused by: sun.security.validator.ValidatorException: PKIX path building failed: sun.security.provider.certpath.SunCertPathBuilderException: unable to find valid certification path to requested target
at sun.security.validator.PKIXValidator.doBuild(PKIXValidator.java:387)
at sun.security.validator.PKIXValidator.engineValidate(PKIXValidator.java:292)
at sun.security.validator.Validator.validate(Validator.java:260)
at sun.security.ssl.X509TrustManagerImpl.validate(X509TrustManagerImpl.java:324)
at sun.security.ssl.X509TrustManagerImpl.checkTrusted(X509TrustManagerImpl.java:229)
at sun.security.ssl.X509TrustManagerImpl.checkServerTrusted(X509TrustManagerImpl.java:124)
at sun.security.ssl.ClientHandshaker.serverCertificate(ClientHandshaker.java:1479)
… 27 more
Caused by: sun.security.provider.certpath.SunCertPathBuilderException: unable to find valid certification path to requested target
at sun.security.provider.certpath.SunCertPathBuilder.build(SunCertPathBuilder.java:145)
at sun.security.provider.certpath.SunCertPathBuilder.engineBuild(SunCertPathBuilder.java:131)
at java.security.cert.CertPathBuilder.build(CertPathBuilder.java:280)
at sun.security.validator.PKIXValidator.doBuild(PKIXValidator.java:382)
… 33 more”

keytool -import -trustcacerts -keystore “C:\Program Files\Java\jdk1.8.0_51\jre\lib\security\cacerts” -storepass changeit -noprompt -alias server_cert -file “D:\360极速浏览器X下载\server.crt”

javax.net.ssl.SSLHandshakeException 表示 Java 应用程序无法验证目标服务器的 SSL/TLS 证书,这是因为目标服务器的证书不被信任。以下是几种常见的解决方案:


1. 确认服务器证书的可信性

  • 检查目标服务器的 SSL 证书是否有效(未过期、未吊销、可信的根证书颁发)。
  • 使用浏览器访问目标服务器(例如 https://example.com),查看是否存在证书错误。
  • 如果服务器使用自签名证书或未被信任的证书,则需要将其添加到 Java 的信任库。

2. 将证书添加到 Java 信任库

如果目标服务器的证书未被默认信任,可以手动将其添加到 Java 信任库:

步骤:
  1. 获取目标服务器的证书

    • 使用以下命令获取证书并保存为 .crt 文件:
      echo | openssl s_client -connect example.com:443 | openssl x509 > server.crt
      
  2. 将证书导入 Java 信任库

    • 使用 keytool 将证书导入:
      keytool -import -trustcacerts -keystore $JAVA_HOME/lib/security/cacerts -storepass changeit -noprompt -alias server_cert -file server.crt
      
    • 注意:
      • $JAVA_HOME 是你的 Java 安装目录。
      • changeit 是 Java 默认的信任库密码。
  3. 重启你的 Java 应用程序


3. 使用自定义的 TrustManager 忽略证书验证(仅限测试)

在测试环境中,如果证书验证失败且无法修改信任库,可以通过自定义 TrustManager 忽略 SSL 验证。

示例代码:
import javax.net.ssl.*;
import java.security.cert.X509Certificate;

public class SSLUtil {
    public static void disableSSLVerification() {
        try {
            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) {}
                }
            };

            SSLContext sc = SSLContext.getInstance("TLS");
            sc.init(null, trustAllCerts, new java.security.SecureRandom());
            HttpsURLConnection.setDefaultSSLSocketFactory(sc.getSocketFactory());
            HttpsURLConnection.setDefaultHostnameVerifier((hostname, session) -> true);
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}
使用方式:

在你的应用程序启动时调用:

SSLUtil.disableSSLVerification();

警告:仅限于开发或调试阶段,切勿在生产环境使用!


4. 升级 Java 或 OkHttp 版本

如果使用的是旧版本的 Java 或 OkHttp,可能会缺乏对某些新型证书的支持。建议:

  • 升级到最新的 Java 版本。
  • 确保 OkHttp 和其依赖(如 okhttp-tls)为最新版本。

5. 使用正确的 CA 证书

如果目标服务器使用特定的 CA 证书链,你可能需要在 Java 应用中明确指定。

示例:
OkHttpClient client = new OkHttpClient.Builder()
    .sslSocketFactory(mySslSocketFactory, myTrustManager)
    .build();

你需要实现自定义的 TrustManager 来加载正确的 CA 证书。


总结

  • 推荐的解决方法: 在生产环境中,建议配置正确的信任库,并确保目标服务器的证书有效。
  • 开发环境: 如果无法解决证书问题,可以使用自定义 TrustManager 暂时绕过验证。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

小黄人软件

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值