最近在客户现场遇到一个棘手的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信任库采坑记的更多相关文章

  1. 分布式改造剧集之Redis缓存采坑记

    Redis缓存采坑记 ​ 前言 ​ 这个其实应该属于分布式改造剧集中的一集(第一集见前面博客:http://www.cnblogs.com/Kidezyq/p/8748961.html),本来按照顺序 ...

  2. Spring Cloud Config采坑记

    1. Spring Cloud Config采坑记 1.1. 问题 在本地运行没问题,本地客户端服务能连上本地服务端服务,可一旦上线,发现本地连不上线上的服务 服务端添加security登录加密,客户 ...

  3. k8s采坑记 - 解决二进制安装环境下证书过期问题

    前言 上一篇k8s采坑记 - 证书过期之kubeadm重新生成证书阐述了如何使用kubeadm解决k8s证书过期问题. 本篇阐述使用二进制安装的kubernetes环境,如何升级过期证书? k8s配置 ...

  4. Redis适配采坑记

    Redis适配采坑记 相对于其他的适配,Redis可以说是非常简单的其中只发现一个坑 问题一: 问题描述: redis认证失败 问题详解: redis连接配置时,本地需要采用password属性,远程 ...

  5. Service worker (@nuxtjs/workbox) 采坑记

    PWA(Progressive Web App)是前端的大趋势,它能极大的加快前端页面的加载速度,得到近乎原生 app 的展示效果(其实难说).PWA 其实是多种前端技术的组合,其中最重要的一个技术就 ...

  6. dubbo初学采坑记

    写在前面的话 dubbo 现在是apache组织旗下的项目,相信国内也有很多人使用.最近一个同事离职,我就接手了他的项目.远程通讯就是用的dubbo框架来实现的.使用Intelij idea 写了一个 ...

  7. tk.mybatis通用工具采坑记

    tk.mybatis通用工具pom <!--mybatis依赖--> <dependency> <groupId>org.mybatis.spring.boot&l ...

  8. 几行代码把Chrome搞崩溃之:HTML5 MP3录音由ScriptProcessorNode升级成AudioWorkletNode采坑记

    关键词: STATUS_ACCESS_VIOLATION AudioContext AudioWorkletNode audioWorklet addModule resume suspended c ...

  9. aidl使用采坑记

    什么是AIDL? AIDL是 Android Interface definition language的缩写,它是一种Android内部进程通信接口的描述语言,通过它我们可以定义进程间的通信接口 A ...

随机推荐

  1. E - Apple Tree(树状数组+DFS序)

    There is an apple tree outside of kaka's house. Every autumn, a lot of apples will grow in the tree. ...

  2. 计算a^b==a+b在(l,r)的对数Codeforces Round #597 (Div. 2)

    题:https://codeforces.com/contest/1245/problem/F 分析:转化为:求区间内满足a&b==0的对数(解释见代码) ///求满足a&b==0在区 ...

  3. 解决一个通过 WebReference 调用 WCF 时自定义 DataContract 类参数提交的问题

    先看一下VS2013自动创建默认的IService1.vb,注意自定义的数据契约 CompositeType ' 注意: 使用上下文菜单上的“重命名”命令可以同时更改代码和配置文件中的接口名“ISer ...

  4. jQuery性能优化与技巧

    1.使用最新版本的jQuery类库 jQuery的每一个新的版本都会较上一版进行Bug修复和一些优化,同时也会包含一些创新,所以建议使用最新版本的jQuery来提高性能,需要注意的是在更换版本之后,要 ...

  5. 火车进出栈 java

    题目描述 一列火车n节车厢,依次编号为1,2,3,…,n.每节车厢有两种运动方式,进栈与出栈,问n节车厢出栈的可能排列方式有多少种. 输入 一个数,n(n<=60000) 输出 一个数s表示n节 ...

  6. Rearrangement

    In a two dimensional array of integers of size 2×n2 \times n2×n, is it possible to rearrange integer ...

  7. 79)PHP,session函数编写的注意事项

    (1)先执行  session_set_save_handler()  在session_start(). (2)那么开启session_start(),有两种方法,一个就是session_start ...

  8. JavaScript 简介与语法

    一.JavaScript简介 ).head里面 ).body里面 (在body内最为严谨) ).</html>之后 //程序上来要执行的部分 [2]三个常用对话框 alert()警告对话框 ...

  9. php配置memcached的扩展。

    (一)安装memcached服务器 1根据系统下载相应版本的memcached服务器版本:如win7(64位=====>memcached-win64/memcached.exe 2.解压到目录 ...

  10. TB3_Autorace之交通杆检测

    利用blob检测算法识别交通杆,控制TB3机器人完成对交通杆的起停动作! 上一篇博文中<TB3_Autorace之路标检测>订阅了原始图像信息,经过SIFT检测识别出道路交通标志,这里我们 ...