javax.net.ssl.SSLPeerUnverifiedException: peer not authenticated

本文分析了在联调HTTPS接口时遇到的“peernotauthenticated”错误,并详细介绍了HTTPS的工作原理、SSL证书的作用及环境配置。通过源码跟踪定位问题原因,并给出了正确的解决方案。

这里写图片描述

Hello,小伙伴好久不见!今天在联调接口时,遇到一个错误,纠结了好久才解决.虽然是粗心引起的,但是也大概明白了引起这个错误的来龙去脉,现在整理一下,分享给大家,希望大家在遇到这个类似问题了,不会太无助;

前言

我们来看下问题发生的大背景;这次我们联调是一个获取单笔订单详情的接口,采用https请求方式.我方是请求方,现需请求能力开发平台(对方)的接口

1.Https加密认证过程是什么样的?

我们来看看接口文档的描述(对方视角):
能力开放平台接口传输采用HTTPS加密传输。接口为RESTFul风格的WebService,信息交互过程为用户按我方提供的webservice地址进行调用,我方接到调用请求后,为用户返回JSON格式组织的信息,用户依据约定的接口规范对数据进行解析。它将用户与移动商城开放平台之间传输的内容进行加密认证。使内容的传输处于安全的加密状态,以防止数据在传输中途被窃取。
客户端认证:由能力开放平台为各个商户自有系统颁发客户端的自签发SSL证书和密钥,通过该证书和密钥来访问能力开放平台接口。
能力开放平台使用自身的根证书为商户自有系统颁发客户端证书和密钥:

  • client.crt:客户端证书文件
  • client.key : 客户端密钥文件
  • 客户端证书密码

2.什么是SSL证书?

SSL 证书就是遵守 SSL协议,由受信任的数字证书颁发机构CA,在验证服务器身份后颁发,具有服务器身份验证和数据传输加密功能。

3.环境情况

  • jdk1.7
  • httpclient_4.2.1.jar

一.场景再现

当我们请求对方接口时,发现报了如下错误

javax.net.ssl.SSLPeerUnverifiedException: peer not authenticated

这里写图片描述

二.刨根问底

1.温故知新

遇到未见过错误,第一时间拿报错信息去问了度娘,首先发现这位兄台的博客,是我明白了
在我们分析什么原因导致了这个问题之前,我们需要搞明白一件事:https的socket工作原理是怎样的?
https的socket工作原理流程图如下:
这里写图片描述
接下来,我们需要搞清楚什么原因会导致这类报错,下面这边博客可以给我们一些思路;peer not authenticated的终极解决方案
在这边文章中,作者介绍可能引发这个报错的几种原因,总结如下:
  首先,要知道导致报这个异常的原因不仅仅是因为证书校验不通过。
  1.在我们通过https链接服务器时,服务器会给我们返回一个证书,这个证书可能经过CA认证,也可能是未认证的自制证书,客户端拿到这个证书后会对这个证书进行验证,如果是经过CA验证的证书,自然证书校验就能通过,自制证书自然就校验不同过,从而导致上边的异常。
  2.证书校验通过后,还需要校验访问的域名是否和证书指定的域名是否匹配。未匹配也会导致如上异常。
  3.上边两步都校验通过了才开始进行握手,但握手也有可能失败,从而导致上边的异常。
  以上三个步骤中任何一个出了问题,都会连接失败。
###2.问题探究
根据报错信息的堆栈信息,我去跟踪了源码,发现在错误的发送在SSLSessionImpl类的下面方法中
这里写图片描述

public Certificate[] getPeerCertificates() throws SSLPeerUnverifiedException {
    if(this.cipherSuite.keyExchange != KeyExchange.K_KRB5 && this.cipherSuite.keyExchange != KeyExchange.K_KRB5_EXPORT) {
        if(this.peerCerts == null) {
            throw new SSLPeerUnverifiedException("peer not authenticated");
        } else {
            return (Certificate[])((Certificate[])this.peerCerts.clone());
        }
    } else {
        throw new SSLPeerUnverifiedException("no certificates expected for Kerberos cipher suites");
    }
}

根据如上源码,我们发现只有peerCerts==null时候,才导致了报错.继续跟踪源码,我们发现下面的方法会给他赋值
这里写图片描述

void setPeerCertificates(X509Certificate[] var1) {
    if(this.peerCerts == null) {
        this.peerCerts = var1;
    }

}

现在有一个问题,什么时候我们会调用这个方法去给他赋值?这个问题困扰了好久,直到看到这位大佬的文章:jdk6出现peer not authenticated问题原因分析与解决
在这篇文章中,我们发现peerCerts是用来存储服务端返回的证书;附上文章中作者的一段代码
1.httpclient未获取到服务器证书
这里写图片描述
2.httpclient获取到了服务器证书
这里写图片描述
这样,我们就基本定位问题原因:没有获取到服务端证书;

三.解决方案

当我们去搜这个问题解决方案时,会发现很多都是重写底层的验证方法来绕过校验,可能这种解决思路适合需要发起https请求,但是没有证书的情况;
因为本次接口调用时一定需要证书的,所以这类解决思路并不适合我,定位了问题的原因以后,经过排除居然是请求地址未加端口号,导致无法获取到服务端证书;

重要的事情说三遍:细心,细心,细心!!!

### 解决 `javax.net.ssl.SSLException: Connection reset` 异常 当遇到 `javax.net.ssl.SSLException: Connection reset` 异常时,这通常意味着客户端与服务器之间的SSL/TLS握手失败或连接被意外重置。以下是几种可能的原因及解决方案: #### 1. 验证HTTPS配置 确保所使用的URL确实是HTTPS URL,并且服务器支持TLS协议。如果尝试通过HTTP访问一个仅提供HTTPS的服务端口,则会引发此类错误。 ```java // 确认URL前缀为 "https" String url = "https://example.com/api"; ``` #### 2. 更新JVM的安全策略文件 有时默认安装的Java环境缺少必要的安全证书更新,可以通过下载最新的Java Cryptography Extension (JCE) Unlimited Strength Jurisdiction Policy Files来增强安全性设置[^1]。 #### 3. 调整信任库和密钥库路径 检查应用程序是否指定了正确的truststore位置以及密码。对于某些特定场景下运行的应用程序来说,可能还需要指定keystore的位置及其对应的密码。 ```properties -Djavax.net.ssl.trustStore=/path/to/truststore.jks \ -Djavax.net.ssl.trustStorePassword=changeit \ -Djavax.net.ssl.keyStore=/path/to/keystore.jks \ -Djavax.net.ssl.keyStorePassword=changeit ``` #### 4. 修改网络参数 调整TCP/IP栈的行为可以减少这种类型的异常发生频率。例如,在发起请求之前关闭Nagle算法(`TcpNoDelay`)或将套接字超时时间设得更短一些。 ```java builder.putHeaderParamsMap("Connection", "keep-alive"); HttpURLConnection conn = ...; conn.setUseCaches(false); conn.setRequestProperty("Keep-Alive", "timeout=15, max=100"); // 设置保持活动的时间和最大请求数量 ``` #### 5. 使用现代加密套件 确认双方都启用了兼容性强且较为安全的加密套件版本。旧版浏览器或应用可能会因为不支持新的TLS标准而无法建立稳定连接。 ```java System.setProperty("https.protocols", "TLSv1.2,TLSv1.3"); ``` 以上措施有助于缓解由不同原因引起的`javax.net.ssl.SSLException: Connection reset`问题。值得注意的是,具体实施哪项方案取决于实际环境中存在的根本原因分析结果。
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值