解决出现javax.net.ssl.SSLHandshakeException: PKIX path building failed 或 sun.security.validator.ValidatorException: PKIX path building failed的问题
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;
}
}



浙公网安备 33010602011771号