最近在客户现场遇到一个棘手的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. 关于dubbo接口性能测试

      最初的压测这个dubbo接口有三种思路: .第一种就是基于业务,比如注册业务,注册成功后,会发送短信消息到用户手机,通过业务调用消息服务,最容易实现,但是业务瓶颈最大导致测试结果不准 .第二种是通 ...

  2. Linux SSH 使用密钥登陆

    Linux SSH 使用密钥登陆 通常我们登录 Linux 服务器,我们需要使用密码进行登录,但是密码存在被暴力破解的可能. 可以将默认服务端口 22 改成其他不常用的端口. 可以设置非常复杂的密码. ...

  3. logstash output kafka ip 设置的坑

    原设置 output { kafka { acks => " enable_metric => false codec => "json" topic_ ...

  4. 方差分析||MSA/MSE|

    应用统计学-方差分析 数值型数据使用线性回归来研究因素对因变量的影响.类别型数据使用方差分析来研究因素对因变量的影响.方差分析是使用方差比MSA/MSE来检验均值是否全相等,即相等是H0假设,而不全相 ...

  5. python多进程之IPC机制以及生产者消费者模型

    1.进程间通信(IPC机制) 第一种:管道 import subprocessres=subprocess.Popen('dir',shell=True, stdout=subprocess.PIPE ...

  6. RAM子账户登录DMS对库进行管理

    前言:阿里云账户是个权限很大的账户,有时候为了不让更多的人知道,但是又必须让别人管理里面某个模块的功能的时候,RAM子账户就显得很重要,所以设置子账户的权限就很有必要了,下面简单设置两种权限(dms上 ...

  7. 为什么前两年大热的VR创业突然冷了?

    不得不说,如果不是<头号玩家>在国内的热映,人们似乎都要忘记VR这个行业了.<头号玩家>中那些带有极强真实色彩的游戏,其实就是VR进化的目标,甚至是巅峰!而里面的角色佩戴的设备 ...

  8. Spring Boot 学习笔记(六) 整合 RESTful 参数传递

    Spring Boot 学习笔记 源码地址 Spring Boot 学习笔记(一) hello world Spring Boot 学习笔记(二) 整合 log4j2 Spring Boot 学习笔记 ...

  9. 一个类似ThinkPHP的Node.js框架——QuickNode

    QuickNode Node.js从QuickNode开始,让restful接口开发更简单! PHP的MVC 作为一名曾经的PHP开发者,我也有过三年多的thinkphp使用经验,那是我学习PHP接触 ...

  10. Nginx笔记总结十五:nginx+keepalive+proxy_cache配置高可用nginx集群和高速缓存

    nginx编译 wget http://labs.frickle.com/files/ngx_cache_purge-2.3.tar.gz ./configure --prefix=/usr/loca ...