HttpClient请求https接口报错处理

原出处:https://blog.csdn.net/qq_36361060/article/details/112801446

现象场景

      项目背景是基于企业微信开发的一套中台系统,本地调试企业微信回调业务逻辑发送第三方HTTPS请求时报错:

PKIX:unable to find valid certification path to requested target

为什么会出现

因为第三方接口服务器(测试环境非生产)配置的CA 根证书不在“受信任的根证书颁发机构”存储区中,导致服务端返回的数字证书没有通过客户端的校验。

      我们了解下https请求的执行过程,如下图

第1步:客户端发起HTTPS请求到指定服务器

第2步:服务端的配置(采用HTTPS协议的服务器必须有一套自己的证书,可以自己制作,也可以向组织申请。区别就是自己颁发的证书需要客户端验证通过,才可以继续访问,而使用受信任的公司申请的证书则不会弹出提示页面。这套证书就是一对公钥和私钥。可以理解为锁(公钥)和钥匙(私钥),钥匙只有你有,每次别人请求你的时候把锁给他,他用你的锁把重要的东西锁起来再发给你,因为只有你有锁的钥匙,所以只有你才能看到被这把锁锁起来的东西)

第3步:服务端向客户端传送证书(包含了很多信息,如证书的颁发机构,过期时间,公钥,公司信息等)

第4步:客户端解析验证证书是否合法,如果不合法则会提示证书存在问题,当证书验证合法后,在本地会生成随机数,然后用证书信息中的公钥对该随机值进行加密(如上所述用锁把这个本地随机数锁起来,只有你有钥匙可以打开这个锁看到这个随机数)

第5步:将加密后的随机数传输到服务端(这个随机数的意义在于让服务端得到后,后续客户端和服务端的通信就可以通过这个随机值来进行通讯的加密解密)

第6步:服务端使用自己的私钥解密信息后得到客户端传过来的随机数(客户端的私钥),通过这个随机数构造对称加密算法,对返回结果内容进行加密。

第7步:服务端向客户端传输加密后的信息

第8步:客户端通过之前生成的随机数(私钥)解密服务端传过来的加密信息,获取了解密后的内容。

      关于第4步证书的验证Java默认情况下回到$JAVA_HOME/jre/lib/security目录下去找,内置的一个证书库cacerts也在当前目录下,当找不到对应的证书来验证服务端的证书,就会抛出如上的异常

如何解决

A:因为我是本地调试接口,最常见的做法就是【手动将第三方接口服务器的安全证书导入到java的cacerts证书库】

      以谷歌浏览器为例,先从请求的第三方服务网站下载证书

证书导出后假设名字叫做 a.cer,接下来将下载的安全证书导入java的cacerts证书库,可以使用Jdk提供的keytool工具(keytool 是个密钥和证书管理工具。它使用户能够管理自己的公钥/私钥对及相关证书,用于(通过数字签名)自我认证(用户向别的用户/服务认证自己)或数据完整性以及认证服务。在JDK 1.4以后的版本中都包含了这一工具,它的位置为%JAVA_HOME%\bin\keytool.exe)

java的cacerts证书库位置:%JAVA_HOME%\jre\lib\security\cacerts

cmd命令切换到该目录下(注意:当切换到 cacerts 文件所在的目录时,才可指定 -keystore cacerts, 否则应该指定全路径),执行如下命令

keytool -import -alias a -keystore cacerts -file D://a.cer

      -alias:指定别名(推荐和证书同名)

      -keystore:密钥库的路径及名称(此处就是你本地的jdk密钥库cacerts文件位置)

      -file:指定证书文件全路径(就是你刚下载的证书所在路径)

此时命令行会提示你输入cacerts证书库的密码,敲入 changeit 即可,这是java中cacerts证书库的默认密码,下一步提示是否信任证书输入:Y

      证书导入成功,可以通过如何下命令查询(密钥仍然是changeit)

B:使用合法的https证书

具体了解HTTPS原理 :https://blog.csdn.net/u013538542/article/details/105416240

————————————————

版权声明:本文为CSDN博主「头有点凉」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。

原文链接:https://blog.csdn.net/qq_36361060/article/details/112801446

你可能感兴趣的:(HttpClient请求https接口报错处理)