https信任库采坑记
最近在客户现场遇到一个棘手的http问题,现象很直接,访问某https的时候报错:
javax.net.ssl.SSLPeerUnverifiedException: peer not authenticated
at sun.security.ssl.SSLSessionImpl.getPeerCertificates(SSLSessionImpl.java:)
at org.apache.http.conn.ssl.AbstractVerifier.verify(AbstractVerifier.java:)
at org.apache.http.conn.ssl.SSLSocketFactory.connectSocket(SSLSocketFactory.java:)
at org.apache.http.impl.conn.DefaultClientConnectionOperator.openConnection(DefaultClientConnectionOperator.java:)
at org.apache.http.impl.conn.AbstractPoolEntry.open(AbstractPoolEntry.java:)
at org.apache.http.impl.conn.AbstractPooledConnAdapter.open(AbstractPooledConnAdapter.java:)
at org.apache.http.impl.client.DefaultRequestDirector.tryConnect(DefaultRequestDirector.java:)
at org.apache.http.impl.client.DefaultRequestDirector.execute(DefaultRequestDirector.java:)
at org.apache.http.impl.client.AbstractHttpClient.execute(AbstractHttpClient.java:)
at org.apache.http.impl.client.AbstractHttpClient.execute(AbstractHttpClient.java:)
at org.apache.http.impl.client.AbstractHttpClient.execute(AbstractHttpClient.java:)
从线程栈来看,是使用httpclient访问https服务的时候报错了,初步猜测是证书没有配置对,就想是不是要配置双向认证。
经过和现场工程师交流,发现这个只是个简单的单向认证,而且在浏览器使用GET发送请求,居然也是返回的200。
于是想到可能是JDK和程序本身的问题,根据httpclient写了个很简单的应用去访问,调用的错误环境下实际使用的JDK,发现也没有问题。
正要开始排查程序问题的时候,现场工程师说是另一个测试的https服务器通过应用程序可以访问通。这下立马有了头绪,可以抓个包对比一下https握手的过程。
果然,差别发现了:能够正常握手的https服务端返回了3个证书,握手错误的只返回了2个证书:

(正确的https服务器的通讯)

(有问题的https服务器的通讯)
看到这里,需要了解一个知识点了:信任库,只有信任库信任了密钥库的证书,才能进行通信。
我们详细看下密钥库的证书链:

发现多出来的证书是Baltimore CyberTrust Root
我们发现jdk能够信任这个多出来的和共有的证书

那为什么应用程序就不行呢,这个时候我们就需要使用jvm属性 -Djavax.net.debug=ssl:handshake了,他可以看到非常详细的https握手信息。
果然,输出的第一段日志就是trustStore is: /home/***/config/security/cacerts,原来使用的不是jdk的默认cacerts,而是自定义了-Djavax.net.ssl.trustStore的值。
那么问题就好解决了,删除即可。
再来看下这个配置的cacerts为啥不能认证,

原来他只信任了这个多出来的证书,机缘凑巧地能够访问测试的机器。验证了为什么能否访问一台https服务器,而另一台访问不了的问题。
另外日志中的一些其他信息我们也可以关注一下,便于遇到类似问题的时候分析:
1)关键字chain可以看到证书链的详细信息
2)两个非常有用的异常
handling exception: javax.net.ssl.SSLHandshakeException: sun.security.validator.ValidatorException: PKIX path building fail
ed: sun.security.provider.certpath.SunCertPathBuilderException: unable to find valid certification path to requested target
IOException in getSession(): javax.net.ssl.SSLHandshakeException: sun.security.validator.ValidatorException: PKIX path bui
lding failed: sun.security.provider.certpath.SunCertPathBuilderException: unable to find valid certification path to requested target
参考:
1、HttpClient javax.net.ssl.SSLPeerUnverifiedException: peer not authenticated when time shifted?
https://stackoverflow.com/questions/24752485/httpclient-javax-net-ssl-sslpeerunverifiedexception-peer-not-authenticated-when
2、Resolving javax.net.ssl.SSLHandshakeException: sun.security.validator.ValidatorException: PKIX path building failed Error?
https://stackoverflow.com/questions/9619030/resolving-javax-net-ssl-sslhandshakeexception-sun-security-validator-validatore
3、javax.net.ssl.SSLHandshakeException的解决办法
https://blog.csdn.net/yiifaa/article/details/73148665
4、How to Analyze Java SSL Errors
https://dzone.com/articles/how-analyze-java-ssl-errors
https信任库采坑记的更多相关文章
- 分布式改造剧集之Redis缓存采坑记
Redis缓存采坑记 前言 这个其实应该属于分布式改造剧集中的一集(第一集见前面博客:http://www.cnblogs.com/Kidezyq/p/8748961.html),本来按照顺序 ...
- Spring Cloud Config采坑记
1. Spring Cloud Config采坑记 1.1. 问题 在本地运行没问题,本地客户端服务能连上本地服务端服务,可一旦上线,发现本地连不上线上的服务 服务端添加security登录加密,客户 ...
- k8s采坑记 - 解决二进制安装环境下证书过期问题
前言 上一篇k8s采坑记 - 证书过期之kubeadm重新生成证书阐述了如何使用kubeadm解决k8s证书过期问题. 本篇阐述使用二进制安装的kubernetes环境,如何升级过期证书? k8s配置 ...
- Redis适配采坑记
Redis适配采坑记 相对于其他的适配,Redis可以说是非常简单的其中只发现一个坑 问题一: 问题描述: redis认证失败 问题详解: redis连接配置时,本地需要采用password属性,远程 ...
- Service worker (@nuxtjs/workbox) 采坑记
PWA(Progressive Web App)是前端的大趋势,它能极大的加快前端页面的加载速度,得到近乎原生 app 的展示效果(其实难说).PWA 其实是多种前端技术的组合,其中最重要的一个技术就 ...
- dubbo初学采坑记
写在前面的话 dubbo 现在是apache组织旗下的项目,相信国内也有很多人使用.最近一个同事离职,我就接手了他的项目.远程通讯就是用的dubbo框架来实现的.使用Intelij idea 写了一个 ...
- tk.mybatis通用工具采坑记
tk.mybatis通用工具pom <!--mybatis依赖--> <dependency> <groupId>org.mybatis.spring.boot&l ...
- 几行代码把Chrome搞崩溃之:HTML5 MP3录音由ScriptProcessorNode升级成AudioWorkletNode采坑记
关键词: STATUS_ACCESS_VIOLATION AudioContext AudioWorkletNode audioWorklet addModule resume suspended c ...
- aidl使用采坑记
什么是AIDL? AIDL是 Android Interface definition language的缩写,它是一种Android内部进程通信接口的描述语言,通过它我们可以定义进程间的通信接口 A ...
随机推荐
- 极简配置,业务上云只需 3min
为了简化账号配置环节,实现本地一键开发部署,Serverless Framework 发布了微信扫码一键登录能力,支持用户在 Serverless Framework 环境扫码注册登陆,用户无需登录控 ...
- MOOC(11)- 获取cookie后存到json中
获取cookie后转成字典格式 把字典格式cookie存到json数据中 需要在表格中写好关键字,判断是否写cookie.是否读cookie 在需要用cookie的时候根据键去json中取值 # 1. ...
- JavaEE基础:过滤器、监听器、拦截器,应用...
写在前面说起Java和C++,很容易想到让人疯狂的指针,Java使用了内存动态分配和垃圾回收技术,让我们从C++的各种指针问题中摆脱出来,更加专心于业务逻辑,不过如果我们需要深入了解java的JVM相 ...
- JavaScript函数创建方式
1.工厂模式 function createPerson(name, job) { var o = new Object() o.name = name o.job = job o.sayName = ...
- iOS UITableView Tips(2)
#TableView Tips(2) (本来想一章就结束TableView Tips,但是发现自己还是太天真了~too young,too simple) ##架构上的优化 在Tips(1)中指出了一 ...
- group compare vs pair compare
成对总体检验是令y1=x11-x12:y2=x21-x22等,令新的随机变量y去做假设检验.此方法适用于排除物理因素影响,对差异更敏感,所以适用于小样本.而使用两个总体均值比较的方法适用于大样本.
- JAVA的堆栈和内存、垃圾回收解说
1.有关java健壮性特点的真相 很多书上都说java健壮性的特点是因为java使用数组代替了c++的指针:c++最令人头痛的问题就是内存问题,java的健壮性使编程人员不用再考虑内存的问题:这种观点 ...
- 3DSMAX安装未完成,某些产品无法安装的解决方法
3DSMAX提示安装未完成,某些产品无法安装该怎样解决呢?,一些朋友在win7或者win10系统下安装3DSMAX失败提示3DSMAX安装未完成,某些产品无法安装,也有时候想重新安装3DSMAX的时候 ...
- 深入理解Javascript中的valueOf与toString
基本上,javascript中所有数据类型都拥有valueOf和toString这两个方法,null除外.它们俩解决javascript值运算与显示的问题,本文将详细介绍,有需要的朋友可以参考下. t ...
- Shell的特殊字符
# 有意义的“#”符合 echo ${PATH#*:} # 参数替换,不是一个注释 echo $(( 2#101011 )) # 进制转换,可以是任意进制,不是一个注释 “.” .字符匹配,这是作为正 ...