首页 > 编程语言 >解决出现javax.net.ssl.SSLHandshakeException: PKIX path building failed 或 sun.security.validator.Validato

解决出现javax.net.ssl.SSLHandshakeException: PKIX path building failed 或 sun.security.validator.Validato

时间:2024-03-22 15:46:23浏览次数:31  
标签:building java String failed PKIX import new security public

From: https://www.cnblogs.com/luoxiao1104/p/16671501.html

当我们从网络上根据url下载文件的时候可能会出现一下异常

错误信息:

 
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

问题原因:

在Java8及高版本以上的版本在源应用程序不信任目标应用程序的证书,因为在源应用程序的JVM信任库中找不到该证书或证书链。也就是目标站点启用了HTTPS 而缺少安全证书时出现的异常

常见的解决方法有三种:

1. 手动生成证书;

2. 忽略证书验证。(建议使用)

3. 在JDK安装目录中删除

三种方式的实现:

1、手动导入安全证书

手动生成证书方法参考大佬博客:手动生成证书方法

2、忽略证书验证(建议使用)

 
public class Base64Util {

    public static String getBase64FromUrl(String fileUrl) {
        InputStream inputStream = null;
        byte[] data = null;
        ByteArrayOutputStream swapStream = null;
        HttpsURLConnection conn = null;
        try {
            URL url = new URL(fileUrl);
            //判断当前文件url是否是https
            if (fileUrl.contains("https:")){
                //是https
                //绕过证书
                SSLContext context = createIgnoreVerifySSL();
                conn = (HttpsURLConnection) url.openConnection();
                conn.setSSLSocketFactory(context.getSocketFactory());
                inputStream = conn.getInputStream();
            }else {
                //当前链接是http
                inputStream =  url.openConnection().getInputStream();
            }

            swapStream = new ByteArrayOutputStream();
            byte[] buff = new byte[100];
            int rc = 0;
            while ((rc = inputStream.read(buff, 0, 100)) > 0) {
                swapStream.write(buff, 0, rc);
            }
            data = swapStream.toByteArray();
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            IOUtils.closeQuietly(inputStream);
            IOUtils.closeQuietly(swapStream);
        }
        return new String(Base64.encodeBase64(data));
    }

    //绕过SSL、TLS证书
    public static SSLContext createIgnoreVerifySSL() throws NoSuchAlgorithmException, KeyManagementException {
        SSLContext sc = SSLContext.getInstance("TLS");
        // 实现一个X509TrustManager接口,用于绕过验证,不用修改里面的方法
        X509TrustManager trustManager = new X509TrustManager() {
            @Override
            public void checkClientTrusted(
                    java.security.cert.X509Certificate[] paramArrayOfX509Certificate,
                    String paramString) throws CertificateException {
            }

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

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

        sc.init(null, new TrustManager[]{trustManager}, null);
        return sc;
    }
}

3、删除JDK安装目录下jre/lib/security的java.security文件的SSLv3, TLSv1, TLSv1.1,(不建议使用,本地环境和生产环境不一样)



 

------------------------ 以下为个人整理的一个文件下载的工具类,仅供参考 ----------------------

开发环境:Windows 10 + JDK21

package com.ruoyi.common.util;


import cn.hutool.core.io.FileUtil;
import lombok.Data;
import lombok.extern.slf4j.Slf4j;

import javax.net.ssl.HttpsURLConnection;
import javax.net.ssl.SSLContext;
import javax.net.ssl.TrustManager;
import javax.net.ssl.X509TrustManager;
import java.io.*;
import java.net.MalformedURLException;
import java.net.URL;
import java.net.URLConnection;
import java.security.KeyManagementException;
import java.security.NoSuchAlgorithmException;
import java.security.cert.CertificateException;

@Data
@Slf4j
public class FileDownloader {

    private String saveDir;         // 服务器上文件存储目录

    public FileDownloader(String saveDir) {
        this.saveDir = saveDir;
    }

    private String getSavePath(String fileName) {
        return saveDir + "/" + fileName;
    }

    public int download(String remoteFileUrl) {
        InputStream is;

        try {
            // 构造URL
            URL url = new URL(remoteFileUrl);
            // 打开连接
            URLConnection con = url.openConnection();
            // 设置请求头
            con.addRequestProperty("User-Agent", "Mozilla/5.0 (compatible; MSIE 10.0; Windows NT 6.1; WOW64; Trident/6.0)");
            // 设置请求超时为5s
            con.setConnectTimeout(5 * 1000);

            if (remoteFileUrl.startsWith("https:")) {
                SSLContext context = createIgnoreVerifySSL();
                con = url.openConnection();
                ((HttpsURLConnection) con).setSSLSocketFactory(context.getSocketFactory());
            }

            is = con.getInputStream();

            // 1K的数据缓冲
            byte[] bs = new byte[1024];
            // 读取到的数据长度
            int len;
            // 输出的文件流
            String name = FileUtil.getName(remoteFileUrl);
            var savepath = getSavePath(name);
            var dir = new File(saveDir);
            if (!dir.exists()) {
                dir.mkdirs();
            }
            OutputStream os = new FileOutputStream(savepath);
            // 开始读取
            while ((len = is.read(bs)) != -1) {
                os.write(bs, 0, len);
            }
            // 完毕,关闭所有链接
            os.close();
            is.close();

            return 1;
        } catch (MalformedURLException e) {
            e.printStackTrace();
        } catch (FileNotFoundException e) {
            System.out.println("下载文件路径不存在:" + remoteFileUrl);
        } catch (IOException e) {
            e.printStackTrace();
        } catch (NoSuchAlgorithmException e) {
            throw new RuntimeException(e);
        } catch (KeyManagementException e) {
            throw new RuntimeException(e);
        }

        return 0;
    }

    /**
     * 参考: https://www.cnblogs.com/luoxiao1104/p/16671501.html
     * 在Java8及高版本以上的版本在源应用程序不信任目标应用程序的证书,因为在源应用程序的JVM信任库中找不到该证书或证书链。也就是目标站点启用了HTTPS 而缺少安全证书时出现的异常
     *
     * @return
     * @throws NoSuchAlgorithmException
     * @throws KeyManagementException
     */
    public static SSLContext createIgnoreVerifySSL() throws NoSuchAlgorithmException, KeyManagementException {
        SSLContext sc = SSLContext.getInstance("TLS");
        // 实现一个X509TrustManager接口,用于绕过验证,不用修改里面的方法
        X509TrustManager trustManager = new X509TrustManager() {
            @Override
            public void checkClientTrusted(
                java.security.cert.X509Certificate[] paramArrayOfX509Certificate,
                String paramString) throws CertificateException {
            }

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

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

        sc.init(null, new TrustManager[]{trustManager}, null);
        return sc;
    }

}

  

 

标签:building,java,String,failed,PKIX,import,new,security,public
From: https://www.cnblogs.com/joeblackzqq/p/18089615

相关文章