最近在客户现场遇到一个棘手的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

最新文章

  1. SQL中CHARINDEX()/INSTR()函数和SUBSTRING()/SUBSTR()函数
  2. Java多线程总结(一)多线程基础
  3. 如何在CentOS 7上安装EPEL源
  4. 自己动手编译hadoop-2.5.2源码
  5. Android: Service中创建窗口显示
  6. php SPL学习
  7. Statement和PreparedStatement批量更新
  8. select跳转
  9. QQ协议的TEA加解密算法
  10. 简单的python协同过滤程序
  11. Tomcat如何实现Comet
  12. CentOS7安装及简单配置(一)
  13. 洛谷P1047校门外的树题解
  14. 最全的MonkeyRunner自动化测试从入门到精通(7)
  15. laravel 同数据表字段比较查询和状态不正规排序
  16. Codeblocks 常用快捷键
  17. ubuntu 换源过程中遇到的坑(一):Could not resolve 'mirrors.aliyun.com'
  18. python win32api 如何用代码模拟点击网页confirm框的确定按钮
  19. 力扣(LeetCode)965. 单值二叉树
  20. 重设域管理员密码-window server 2008 R2

热门文章

  1. 系统学习javaweb4----CSS层叠样式表(结束)
  2. HTTP Status 400,400 (Bad Request)
  3. 可用倍增LCA解题
  4. 蒲公英Ghost Win 7 Sp1(x86/x64)旗舰版 201910
  5. Qt unsigned char *与QString之间的相互转换
  6. Linux 系统优化参数总结
  7. 为什么前两年大热的VR创业突然冷了?
  8. ZOJ-1177-K-Magic Number
  9. 吴裕雄--天生自然 R语言开发学习:回归(续一)
  10. Mac下如何使用homebrew