文档章节

解析Java为什么不接受合法的HTTPS证书

joymufeng
 joymufeng
发布于 2017/09/07 20:23
字数 1533
阅读 1402
收藏 43

转载请注明joymufeng,欢迎访问PlayScala社区(http://www.playscala.cn/)

在我们使用Java调用远程接口或是抓取数据时经常会发生以下错误:

Caused by: sun.security.validator.ValidatorException: PKIX path building failed: sun.security.provider.certpath.SunCertPathBuilderException: unable to find valid certification path to requested target
	at sun.security.validator.PKIXValidator.doBuild(PKIXValidator.java:387)
	at sun.security.validator.PKIXValidator.engineValidate(PKIXValidator.java:292)
	at sun.security.validator.Validator.validate(Validator.java:260)
	at sun.security.ssl.X509TrustManagerImpl.validate(X509TrustManagerImpl.java:324)
	at sun.security.ssl.X509TrustManagerImpl.checkTrusted(X509TrustManagerImpl.java:281)
	at sun.security.ssl.X509TrustManagerImpl.checkServerTrusted(X509TrustManagerImpl.java:136)
	at sun.security.ssl.ClientHandshaker.serverCertificate(ClientHandshaker.java:1496)
	... 27 more
Caused by: sun.security.provider.certpath.SunCertPathBuilderException: unable to find valid certification path to requested target
	at sun.security.provider.certpath.SunCertPathBuilder.build(SunCertPathBuilder.java:141)
	at sun.security.provider.certpath.SunCertPathBuilder.engineBuild(SunCertPathBuilder.java:126)
	at java.security.cert.CertPathBuilder.build(CertPathBuilder.java:280)
	at sun.security.validator.PKIXValidator.doBuild(PKIXValidator.java:382)
	... 33 more

这个错误表明Java虚拟机在请求远程HTTPS服务器时无法验证证书的有效性,由于担心HTTPS中间人劫持,所以抛出错误警告调用者。可是奇怪的是这个HTTPS链接在浏览器中可以被正确访问,这是为什么呢?别急,听我慢慢道来。

什么是HTTPS/SSL证书?

HTTPS/SSL证书是由权威CA(Certificate Authority)机构颁发,主要用于服务器(应用)数据传输链路加密和身份认证,以及绑定网站域名。主要有EV SSL证书(Extended Validation SSL),OV SSL证书(Organization Validation SSL)和DV SSL证书(Domain Validation SSL)等。不同的证书类型在浏览器标识上会享受不同的待遇,例如EV、OV证书在浏览器地址栏上会显示企业名称,当然也意味着你在向CA机构申请证书时要付更多的钱,走更多的审核流程。通常DV证书就足够用了,审核流程简单,并且很便宜。

我们上面说到HTTPS/SSL证书是由CA机构颁发的,为了方便运营,CA机构下面还有很多的代理商,这些代理商就是所谓的中间证书颁发机构(Intermediate Certificate Authority),一些大的代理商下面还会继续设置代理商。通常我们的证书都是在代理商或者叫中间证书颁发机构那里申请的。

如何验证证书的有效性?

HTTPS/SSL证书是一种非对称加密技术,HTTPS/SSL证书中包含了所有者的一些基本信息和对外公开的公钥,也就是说HTTPS/SSL证书其实就是所有者的一张名片,但是谁能证明这张名片上的信息是否属实呢? 就像是你拿着一个破手镯,到马路上然后逢人就说"我是马云私生子,看,这是他留给我的手镯,上面还有他的签名。",显然不会有人相信你。但是如果马云站出来,一把抢过手镯仔细端详一番后,抱着你痛哭流涕,那么这个手镯确实可以证明你是马云私生子。HTTPS/SSL证书的作用就像这个手镯,需要经过权威机构认证,通过了认证才会得到大家的认可。所以你的证书需要经过你的代理商认证,代理商的证书需要经过父级代理商认证,... ,这样层层认证一直到顶层的CA机构。所以:

HTTPS/SSL证书其实是一个证书链,这条链上的所有证书均合法才能表明证书本身的合法性。

Java的HTTPS/SSL证书错误分析

搞清楚证书链概念后我们再回头看一下本文开头的错误,其实原因很简单。浏览器成功地完成了整条证书链的校验,所以认为证书是合法的;而在Java中未能完成整条证书链的校验,例如无法验证某个中间证书颁发机构的合法性,所以导致最终认证失败。例如域名chatbot.cn的证书链如下:

中间证书COMODO RSA Domain Validation Secure Server CA的指纹为:

‎33 9c dd 57 cf d5 b1 41 16 9b 61 5f f3 14 28 78 2d 1d a6 39

CA机构COMODO SECURE的指纹为:

‎af e5 d2 44 a8 d1 19 42 30 ff 47 9f e2 f8 97 bb cd 7a 8c b4

下面我们看下Windows证书管理器中收录的CA证书和中间证书,单击开始-运行,输入certmgr.msc回车,单击菜单栏【操作】-【查找证书】, 输入COMODO,分别搜索“中间证书颁发机构”和“受信任的根证书颁发机构”,结果如下:

该证书的指纹为:

‎33 9c dd 57 cf d5 b1 41 16 9b 61 5f f3 14 28 78 2d 1d a6 39

该证书指纹为:

‎af e5 d2 44 a8 d1 19 42 30 ff 47 9f e2 f8 97 bb cd 7a 8c b4

由于在Windows上整条证书链的认证是完整的,所以在浏览器中可以成功验证证书的有效性。

我们再来看一下Java这边,Java拥有自己的keystore(通常位于$JAVA_HOME/lib/security/cacerts)用于存储CA证书和中间证书,双击$JAVA_HOME/bin/javacpl.exe打开Java控制台,单击【安全】- 【管理证书】,选择【系统】选项卡,然后单击证书类型下拉框查看相关证书。其实还有一种更简单的办法查看Java的信任证书列表,执行如下命令:

keytool -keystore "$JAVA_HOME\jre\lib\security\cacerts" -storepass changeit -list

该命令输出结果如下:

C:\Users\Lenovo>keytool -keystore "D:\Software\jdk1.8.0_111\jre\lib\security\cacerts" -storepass changeit -list

密钥库类型: JKS
密钥库提供方: SUN

您的密钥库包含 104 个条目

digicertassuredidrootca, 2008-4-16, trustedCertEntry,
证书指纹 (SHA1): 05:63:B8:63:0D:62:D7:5A:BB:C8:AB:1E:4B:DF:B5:A8:99:B2:4D:43
comodorsaca, 2015-5-12, trustedCertEntry,
证书指纹 (SHA1): AF:E5:D2:44:A8:D1:19:42:30:FF:47:9F:E2:F8:97:BB:CD:7A:8C:B4
thawtepremiumserverca, 2015-5-21, trustedCertEntry,
...
...

在上面的输出中,我们只能找到CA机构COMODO SECURE的指纹(上面的倒数第4行),而找不到中间证书COMODO RSA Domain Validation Secure Server CA的指纹,所以在Java中无法验证整条证书链的有效性,所以导致Java程序在通过HTTPS协议访问chatbot.cn域名时发生证书错误。通常的解决办法是在Http Client端设置忽略证书错误,或是将缺少的中间证书导入Java keystore,详情请Google之。

 

© 著作权归作者所有

共有 人打赏支持
joymufeng
粉丝 82
博文 69
码字总数 58602
作品 2
杨浦
高级程序员
Tomcat在Linux上的安装与配置

Tomcat在Linux上的安装与配置 以下使用的Linux版本为: Redhat Enterprise Linux 7.0 x86_64,Tomcat版本为tomcat-7.0.54. 1.下载JDK与Tomcat. jdk下载地址: http://www.oracle.com/technetwo......

不忘初心77
06/26
0
0
JA-SIG(CAS)学习笔记1

实验背景: 系统环境: Windows XP | SUN JDK1.6U4 | Tomcat6.0.14 | CAS Server 3.1.1 + CAS Client 2.1.1 主机完整名称: Linly 浏览器: FireFox V2.0.0.11 实验步骤: STEP 1,搭建Java ......

张xtpgyaps
2011/06/30
0
1
从Java代码中访问 HTTPS 协议

有个互联网上的网址:https://wtsz.jyzq.cn/ywcl.jsp?type=l&yybdm=1100&market=Z&userName=11009341&pwd=870221&ip=3.3.3.3&serverName=jyzq.cn,是HTTPS协议的,如何通过JAVA程序能够调用该......

圣洁之子
2015/03/17
0
0
解决 『SunCertPathBuilderException:unable to find valid certification path to requested target』 问题

版权声明:本文为 Abracadabra(爱博客大伯) 原创文章,转载请注明作者及链接,请勿用于任何商业用途。 https://blog.csdn.net/u013553529/article/details/82895226 解决 『SunCertPathBuil...

爱博客大伯
09/29
0
0
keytool生成证书与Tomcat SSL配置

一、Keytool介绍 Keytool是一个Java数据证书的管理工具。Keytool将密钥(key)和证书(certificates)存在一个称为keystore的文件中在keystore里,包含两种数据: 1. 密钥实体(Key entity)...

Lofo
2014/09/16
0
0

没有更多内容

加载失败,请刷新页面

加载更多

【大福利】极客时间专栏返现二维码大汇总

我已经购买了如下专栏,大家通过我的二维码你可以获得一定额度的返现! 然后,再给大家来个福利,只要你通过我的二维码购买,并且关注了【飞鱼说编程】公众号,可以加我微信或者私聊我,我再...

飞鱼说编程
59分钟前
1
0
Spring5对比Spring3.2源码之容器的基本实现

最近看了《Spring源码深度解析》,该书是基于Spring3.2版本的,其中关于第二章容器的基本实现部分,目前spring5的实现方式已有较大改变。 Spring3.2的实现: public void testSimpleLoad(){...

Ilike_Java
今天
1
0
【王阳明心学语录】-001

1.“破山中贼易,破心中贼难。” 2.“夫万事万物之理不外于吾心。” 3.“心即理也。”“心外无理,心外无物,心外无事。” 4.“人心之得其正者即道心;道心之失其正者即人心。” 5.“无...

卯金刀GG
今天
2
0
OSChina 周三乱弹 —— 我们无法成为野兽

Osc乱弹歌单(2018)请戳(这里) 【今日歌曲】 @ _刚刚好: 霸王洗发水这波很骚 手机党少年们想听歌,请使劲儿戳(这里) hahahahahahh @嘻酱:居然忘了喝水。 让你喝可乐的话, 你准忘不了...

小小编辑
今天
9
0
vm GC 日志 配置及查看

-XX:+PrintGCDetails 打印 gc 日志 -XX:+PrintTenuringDistribution 监控晋升分布 -XX:+PrintGCTimeStamps 包含时间戳 -XX:+printGCDateStamps 包含时间 -Xloggc:<filename> 可以将数据保存为......

Canaan_
昨天
0
0

没有更多内容

加载失败,请刷新页面

加载更多

返回顶部
顶部