问题描述

首先来看一段报错:

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

该段报错主要原因是在 Java 代码中发送了 https 请求,而该 https 网站的证书又不被 JDK 信任。

问题分析

https 协议对于开发者而言其实只是多了一步证书验证的过程。对于 JDK 而言这个证书通常情况下被jdk/jre/security/cacerts所管理。
里面证书包含两种情况:

  • 1、机构所颁发的被认证的证书,这种证书的网站在浏览器访问时 https 头一般会显示为绿色或者一个灰色小锁的标识。
  • 2、个人所设定的证书,这种证书的网站在浏览器里 https 头显示为红色(证书无效),且需要点击信任该网站才能继续访问。

而点击信任这一步的操作,就是我们在 java 代码访问 https 网站时区别于 http 请求需要做的事情。

解决方法

如果使用的是机构所颁发的被认证的证书,则不需要做任何修改,即可使用。

其实有好几种解决方法,这里选择了将证书导入java的运行环境中。

# 本地证书导入到本地java环境
cd /usr/local/java/jre/lib/security/
# 备份已有的证书列表
cp cacerts cacerts.bak

# 查询是否有某一证书
keytool -list -keystore cacerts | grep changyan

# 默认密钥 changeit 

# 向java环境添加证书(注意修改jdk home路径和本地证书位置)
keytool -import -keystore /usr/local/java/jre/lib/security/cacerts -file /root/server.crt -alias xxx.com

## 从java环境删除证书
keytool -delete -alias xxx.com -keystore /usr/local/java/jre/lib/security/cacerts

Q.E.D.


Think Big, Act Small