报错 | PKIX path building failed: ...SunCertPathBuilderException:unable to find valid certification...


01 问题场景

在Java中访问不受信任的HTTPS网站时,会提示报错信息:

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

翻译成中文是:

PKIX路径构建失败:sun.security.provider.certpath.SunCertPathBuilderException:无法找到请求目标的有效认证路径。

这是由于JVM (Java Virtual Machine) 默认信任证书不包含该目标网站的SSL证书,导致无法建立有效的信任链。

02 分析问题

JVM自己维护有一个默认的信任证书,是一个没有后缀名的文件,文件名为cacerts,位于java安装路径下,例如:

C:\Program Files\Java\jdk-17\lib\security\cacerts

当Java访问https的网站时,通常不会出现这一异常,但有的https网站,因为种种原因,存在证书不受信任的问题,使用浏览器访问会出现如下界面:

在这里插入图片描述
Java访问这种网站就会导致报错。

03 三种解决方案

经过我的一番搜寻,网上一般有解决方案:

  1. 信任所有SSL证书
    参考:https://developer.aliyun.com/article/812846
    这种方案不失为一种解决办法,但除了存在安全问题,还会对代码造成侵入,且在框架项目中不易集成。

  2. 将不信任的证书加入到JVM默认信任证书
    参考:https://www.cnblogs.com/qixing/p/11883494.html
    这种方案避免了代码入侵的问题,但想到要对java自带的默认文件动手动脚,且加入的还是不受信任的证书,多少有些不合适,而且加入后以后可能会忘记复原,或是要备份原始默认文件。

  3. 单独为不信任的网站生成证书并在项目中指定
    这也是本文使用的方案,避免了上面两个方案的问题。

04 解决步骤

4.1 获取目标网站的SSL证书

因为我是访问自己的网站,我作为站长,有自己的证书,就不涉及获取目标网站证书的问题,如果需要获取,也不困难,直接在浏览器网页左上角点击图标,进行导出即可(可自行百度),导出后通常为.crt.pem文件。

4.2 创建一个Java信任库

创建一个Java信任库(Truststore),并将目标网站的SSL证书导入其中。使用java自带的keytool命令行工具来完成此操作。在cmd中使用命令:

keytool -import -keystore <信任库文件路径> -storepass <密码> -alias alias_for_certificate -file <证书文件路径>

该命令由4个部分组成:
keytool -import 用于导入的命令
-keystore <信任库文件路径> 希望生成的信任库文件,例如路径可以写:C:\Users\abc\Desktop\truststore.jks
-storepass <密码> 设置一个信任库密码
-alias alias_for_certificate -file <证书文件路径> 指定要导入的证书文件,例如可以写:C:\Users\abc\Desktop\cert.pem

4.3 告知JVM使用信任库

在你的Java应用程序中,告知JVM使用你刚刚创建的信任库。使JVM在运行时加载该信任库。
通过设置以下系统属性来实现:

System.setProperty("javax.net.ssl.trustStore", "<信任库文件路径>");	// 刚才填写的路径
System.setProperty("javax.net.ssl.trustStorePassword", "<密码>");	// 刚才填写的密码

这样问题就得到解决了!

05 补充

5.1 命令行提示没有keytool的解决

通常是因为jdk没有加入环境变量造成的,可以加入环境变量再试,或者直接cd到keytool所在的路径执行命令,例如我的keytool工具存放位置在:C:\Program Files\Java\jdk-17\bin目录下。

5.2 SpringBoot项目中如何指定信任库

将上面的两行代码放到SpringApplication.run()所在位置即可。示例:

@SpringBootApplication
public class DemoApplication {
    public static void main(String[] args) {
        SpringApplication.run(DemoApplication.class, args);
        // 代码放到这里 可以使用相对路径
        System.setProperty("javax.net.ssl.trustStore", "C:\\Users\\truststore.jks");
        System.setProperty("javax.net.ssl.trustStorePassword", "123456");
    }
}
### 解决Content Security Policy (CSP) img-src 'self' data: base64 错误 当遇到 `img-src` CSP 指令违反策略的问题时,通常是由于网页尝试加载不符合指定来源的图像资源引起的。以下是可能的原因以及解决方案: #### 原因分析 1. **CSP 策略定义不足** 当前 CSP 中设置了 `img-src 'self'`,这意味着只有来自同一源(即当前域名)的图片才能被加载。如果页面中有通过 `data:` 或者其他外部 URL 加载的图片,则会被阻止[^1]。 2. **Base64 图像嵌入问题** 使用 Base64 编码的内联图像是一种常见的优化手段,但如果未显式允许 `data:` 协议,在 CSP 下这些图像将无法正常显示。 3. **动态生成的内容冲突** 动态注入 HTML 内容可能导致意外行为,尤其是当内容中包含不受信任的数据时,这可能会触发 CSP 警告或错误。 --- #### 解决方案 ##### 方法一:扩展 `img-src` 定义范围 修改 `<meta>` 标签中的 CSP 策略以支持更多类型的图像来源。例如: ```html <meta http-equiv="Content-Security-Policy" content="default-src 'self'; script-src 'self'; img-src 'self' data:;"> ``` 上述配置表示除了允许同源的图片外,还允许基于 Base64 的编码图像加载。 ##### 方法二:调整服务器端响应头 如果 CSP 是由 HTTP 头部设置而非 `<meta>` 标签控制,则需更新 Web 服务器配置文件。对于 Nginx 和 Apache 分别有以下示例: - **Nginx** ```nginx add_header Content-Security-Policy "default-src 'self'; script-src 'self'; img-src 'self' data;"; ``` - **Apache** ```apache Header set Content-Security-Policy "default-src 'self'; script-src 'self'; img-src 'self' data;" ``` 以上更改确保浏览器能够识别并接受 Base64 数据作为合法的图像来源[^1]。 ##### 方法三:移除违规代码片段 检查前端代码是否存在非法调用第三方资源的情况。比如某些框架库自动插入了跨域请求或者使用了未经许可的协议加载媒体资产。清理掉不必要的部分有助于减少潜在风险。 ##### 方法四:启用报告机制捕获异常事件 为了更好地监控实际运行状况,建议开启 CSP Reports 功能收集反馈日志以便后续改进措施制定。 ```html <meta http-equiv="Content-Security-Policy" content="... report-uri /csp-report-endpoint"> ``` 此操作会把每次发生的违禁访问记录提交至指定 URI 地址供管理员审查处理。 --- ### 示例代码展示 下面给出一段简单的 PHP 页面演示如何正确应用增强后的 CSP 设置防止类似问题再次发生。 ```php <?php header('Content-Security-Policy: default-src \'self\'; script-src \'self\'; img-src \'self\' data:'); ?> <!DOCTYPE html> <html lang="en"> <head> <title>CSP Example</title> </head> <body> <!-- 合法本地图片 --> <img src="/images/example.jpg"> <!-- 合法base64编码图片 --> <img src="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAUA..." alt="Embedded Image"> <h1>Secure Page Loaded Successfully!</h1> </body> </html> ``` ---
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

程序猿林仔

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

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

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

打赏作者

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

抵扣说明:

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

余额充值