HttpClient 4.1的SSL“Peer Not Authenticated”错误

我正在构建一个简单的应用程序监视器来轮询我们的一个API URL并向我们发送电子邮件,如果它无法从响应中获取HTTP 200状态代码(这表明我们的API因某种原因而关闭)。

我正在使用HttpClient 4.1 (这很重要,因为它的API与3.x差别很大 )。

我们的API使用SSL是安全的,但输入:

http://example.com/our-api

进入Web浏览器重定向到

https://example.com/our-api

没有造成任何错误。

当HttpClient尝试访问此URL( http://example.com/our-api )时,它会因javax.net.ssl.SSLPeerUnverifiedExceptionexception而失败,并显示一条消息:

同行未经过身份validation

我发现这对其他人来说发生了很多事情,正如这篇文章所certificate的那样(这也提供了一些规避这个问题的方法 – 我今晚将尝试和实施的解决方案)。

这个其他post(和其他类似的post)没有做的是解释为什么这首先发生! 所以,而不是问“我该如何解决这个问题?” 我想我会问“ 为什么会发生这种情况? ”在我提前解决其中一个建议的解决方案之前,我想知道我试图解决的问题是什么;-)

如果服务器的证书是自签名的,那么这是按设计工作的,您必须将服务器的证书导入密钥库。

假设服务器证书由知名CA签名,则会发生这种情况,因为现代浏览器可用的CA证书集远远大于JDK / JRE附带的有限集。

您提到的其中一个post中给出的EasySSL解决方案只会掩盖错误,您不会知道服务器是否具有有效证书。

您必须将正确的根CA导入密钥库以validation证书。 有一个原因你不能用股票SSL代码解决这个问题,那就是为了防止你编写那些表现得像是安全但不安全的程序。

这是抛出的时候

…对等方无法识别自身(例如;没有证书,正在使用的特定密码套件不支持身份validation,或者在SSL握手期间未建立对等身份validation)抛出此exception。

可能导致此exception的原因(堆栈跟踪在哪里)将显示抛出此exception的原因。 很可能Java附带的默认密钥库不包含(并信任)正在使用的TTP的根证书。

答案是检索根证书(例如,从您的浏览器SSL连接),将其导入cacerts文件并使用Java JDK提供的keytool信任它。 否则,您必须以编程方式分配另一个信任库。

我不是Java开发人员,但使用java应用程序来测试RESTful API。 为了让我修复错误,我必须在网络服务器中安装中间证书才能使错误消失。 我使用的是lighttpd,原始证书安装在IIS服务器上。 希望能帮助到你。 这些是我在服务器上遗漏的证书。

  • CA.crt
  • UTNAddTrustServer_CA.crt
  • AddTrustExternalCARoot.crt
 keytool -import -v -alias cacerts -keystore cacerts.jks -storepass changeit -file C:\cacerts.cer