peer not authenticated的终极解决方案
一、前述
使用httpclient发起https请求时,可能会遇到如下异常:
javax.net.ssl.SSLPeerUnverifiedException: peer not authenticated
at sun.security.ssl.SSLSessionImpl.getPeerCertificates(SSLSessionImpl.java:397)
at org.apache.http.conn.ssl.AbstractVerifier.verify(AbstractVerifier.java:128)
at org.apache.http.conn.ssl.SSLSocketFactory.createSocket(SSLSocketFactory.java:399)
at org.apache.http.impl.conn.DefaultClientConnectionOperator.openConnection(DefaultClientConnectionOperator.java:143)
网上搜索也能找到一大堆的解决方案,但大部分都类似,就是跳过证书的验证,于是跟着稀里糊涂的将代码拷贝下来使用,结果呢?有的能解决,有的依旧报这个错误。到底咋回事呢,接下来就说说这个问题的解决方案。
二、缘由
首先,要知道导致报这个异常的原因不仅仅是因为证书校验不通过。
都知道,在我们通过https链接服务器时,服务器会给我们返回一个证书,这个证书可能经过CA认证,也可能是未认证的自制证书,客户端拿到这个证书后会对这个证书进行验证,如果是经过CA验证的证书,自然证书校验就能通过,自制证书自然就校验不同过,从而导致上边的异常。
证书校验通过后,还需要校验访问的域名是否和证书指定的域名是否匹配。未匹配也会导致如上异常。
上边两步都校验通过了才开始进行握手,但握手也有可能失败,从而导致上边的异常。
以上三个步骤中任何一个出了问题,都会连接失败。
三、解决方法
通过网上搜索我们大部分都会找到类似如下的解决方案:
SSLContext sslContext;
try {
sslContext = SSLContext.getInstance("SSL");
// set up a TrustManager that trusts everything
try {
sslContext.init(null,
new TrustManager[] { new X509TrustManager() {
public X509Certificate[] getAcceptedIssuers() {
return null;
} public void checkClientTrusted(
X509Certificate[] certs, String authType) {
} public void checkServerTrusted(
X509Certificate[] certs, String authType) {
}
} }, new SecureRandom());
} catch (KeyManagementException e) {
}
SSLSocketFactory ssf = new SSLSocketFactory(sslContext,SSLSocketFactory.ALLOW_ALL_HOSTNAME_VERIFIER);
这个解决方案针对以上的三个步骤中的第一步,就是放弃对证书的校验,但是第二部还可能有问题,要想彻底解决还需要跳过对域名的校验。这里给出最终的解决方案:
try {
SSLContext sslContext = SSLContext.getInstance("TLS");
X509TrustManager tm = new X509TrustManager() {
@Override
public void checkClientTrusted(X509Certificate[] x509Certificates, String s) throws CertificateException {
}
@Override
public void checkServerTrusted(X509Certificate[] x509Certificates, String s) throws CertificateException {
}
@Override
public X509Certificate[] getAcceptedIssuers() {
return null;
}
};
sslContext.init(null,new TrustManager[]{tm},null);
sslSocketFactory = new SSLSocketFactory(sslContext,new X509HostnameVerifier(){
@Override
public boolean verify(String s, SSLSession sslSession) {
return true;
}
@Override
public void verify(String host, SSLSocket ssl) throws IOException {
}
@Override
public void verify(String host, X509Certificate cert) throws SSLException {
}
@Override
public void verify(String host, String[] cns, String[] subjectAlts) throws SSLException {
}
});
} catch (GeneralSecurityException e) {
log.error("create SSLSocketFactory error:{}",e);
}
return sslSocketFactory;
这里不仅放弃对证书的校验,也放弃对hostname的校验,通过空实现X509HostnameVerifier类。
以上这个解决方案就会彻底解决问题吗?不一定,还有一个步骤就是握手的步骤也可能出问题,怎么判断是不是握手步骤出了问题呢?可以在代码里做如下设置:
System.setProperty("javax.net.debug","ssl");
做了以上设置后,就可以打印https建立连接的日志了,如下:
true
addingastrustedcert:
证书内容略去
triggerseedingofSecureRandom
doneseedingSecureRandom
executingrequestGETHTTP/1.1
Ignoringunavailableciphersuite:TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA
Ignoringunavailableciphersuite:TLS_DHE_RSA_WITH_AES_256_CBC_SHA
Ignoringunavailableciphersuite:TLS_ECDH_RSA_WITH_AES_256_CBC_SHA
Ignoringunsupportedciphersuite:TLS_DHE_DSS_WITH_AES_128_CBC_SHA256
Ignoringunsupportedciphersuite:TLS_DHE_DSS_WITH_AES_256_CBC_SHA256
Ignoringunsupportedciphersuite:TLS_DHE_RSA_WITH_AES_128_CBC_SHA256
Ignoringunsupportedciphersuite:TLS_ECDH_RSA_WITH_AES_128_CBC_SHA256
Ignoringunsupportedciphersuite:TLS_DHE_RSA_WITH_AES_256_CBC_SHA256
Ignoringunsupportedciphersuite:TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA384
Ignoringunsupportedciphersuite:TLS_ECDH_ECDSA_WITH_AES_256_CBC_SHA384
Ignoringunsupportedciphersuite:TLS_RSA_WITH_AES_256_CBC_SHA256
Ignoringunavailableciphersuite:TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA
Ignoringunsupportedciphersuite:TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256
Ignoringunsupportedciphersuite:TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA384
Ignoringunavailableciphersuite:TLS_DHE_DSS_WITH_AES_256_CBC_SHA
Ignoringunsupportedciphersuite:TLS_ECDH_RSA_WITH_AES_256_CBC_SHA384
Ignoringunsupportedciphersuite:TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256
Ignoringunsupportedciphersuite:TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA256
Ignoringunavailableciphersuite:TLS_ECDH_ECDSA_WITH_AES_256_CBC_SHA
Ignoringunavailableciphersuite:TLS_RSA_WITH_AES_256_CBC_SHA
Ignoringunsupportedciphersuite:TLS_RSA_WITH_AES_128_CBC_SHA256
Allowunsaferenegotiation:false
Allowlegacyhellomessages:true
Isinitialhandshake:true
Issecurerenegotiation:false
%%Nocachedclientsession
***ClientHello,TLSv1
……
main,WRITE:TLSv1Handshake,length=181
main,READ:TLSv1Alert,length=2
main,RECVTLSv1ALERT:fatal,handshake_failure
main,calledcloseSocket()
main,handlingexception:javax.net.ssl.SSLHandshakeException:Receivedfatalalert:handshake_failure
通过最后一个词组“handshake_failure”,你一定可以确定是握手失败了。这一般是因为客户端的加密机制太简单,服务器认为不安全,握手失败。
握手失败解决方案就比较简单,下载一个UnlimitedJCEPolicyJDK7.zip 。在http://www.oracle.com/technetwork/java/javase/downloads/index.html下载就好了。里面包含了两个jar。在你的/lib/security,替换后,重新运行看看。
如果以上这些还没能解决,那我也是不知道了,可以留言,我跟你一块找答案^_^。
peer not authenticated的终极解决方案的更多相关文章
- peer not authenticated error
问题背景 系统:OS X El Capitan,10.11.2 IDE:Android Studio 2.0 Preview Java:1.8.0_65 Gradle:2.3 clone了代码后,在i ...
- 导入安卓项目的时候,发生错误:Cause: peer not authenticated
导入安卓项目时出现Cause: peer not authenticated. 在网上搜了解决方案,都没有凑效.后来干脆插上手机直接debug安装,竟然成功了,成功了,成功了!!!! 然后再次buil ...
- Eclipse不自动编译java文件的终极解决方案
最近我的eclipse经常犯傻,项目中总是有很多,启动项目也是没有启动类.查了下项目中生成的class文件,我靠竟然没有,或者还是以前的.原来是eclipse犯傻了,它没帮我自动编译java文件.一般 ...
- 【转】JSP中文乱码问题终极解决方案
原文地址:http://blog.csdn.net/beijiguangyong/article/details/7414247 在介绍方法之前我们首先应该清楚具体的问题有哪些,笔者在本博客当中论述的 ...
- Xcode-调试断点不能停在代码区终极解决方案
转发 调试断点不能停在代码区终极解决方案: http://mobile.51cto.com/iphone-390082.htm
- VIM、GVIM在WINDOWS下中文乱码的终极解决方案
文章转自:http://www.liuhuadong.com/archives/68 vim.gvim在windows下中文乱码的终极解决方案在windows下vim的中文字体显示并不好,所以我们需要 ...
- Android大图片裁剪终极解决方案(上:原理分析)
转载声明:Ryan的博客文章欢迎您的转载,但在转载的同时,请注明文章的来源出处,不胜感激! :-) http://my.oschina.net/ryanhoo/blog/86842 约几个月前,我正 ...
- 【原创】CHROME 最小字体限制为12PX的终极解决方案
CHROME 最小字体限制为12PX的终极解决方案 本文由五月雨恋提供,转载请注明出处. 相信不少做网站的用户会有这样一个问题,Chrome 默认最小字体是12px(最新版英文也有此问题),这个是 C ...
- 绝对好文C#调用C++DLL传递结构体数组的终极解决方案
C#调用C++DLL传递结构体数组的终极解决方案 时间 2013-09-17 18:40:56 CSDN博客相似文章 (0) 原文 http://blog.csdn.net/xxdddail/art ...
随机推荐
- 日期格式代码出现两次的错误 ORA-01810
错误的原因是使用了两次MM . 一.Oracle中使用to_date()时格式化日期需要注意格式码 如:select to_date('2005-01-01 11:11:21','yyyy-MM-dd ...
- Asp.Net MVC中使用StreamReader读取“Post body”之应用场景。
场景:有三个市场(Global.China.USA),对前台传过来的数据有些验证需要细化到每个市场去完成. 所以就出现了基类(Global)和派生类(China.USA) 定义基类(Global)Pe ...
- Vue.js 2.0 和 React、Augular等其他框架的全方位对比
引言 这个页面无疑是最难编写的,但也是非常重要的.或许你遇到了一些问题并且先前用其他的框架解决了.来这里的目的是看看Vue是否有更好的解决方案.那么你就来对了. 客观来说,作为核心团队成员,显然我们会 ...
- 构建通用的 React 和 Node 应用
这是一篇非常优秀的 React 教程,这篇文章对 React 组件.React Router 以及 Node 做了很好的梳理.我是 9 月份读的该文章,当时跟着教程做了一遍,收获很大.但是由于时间原因 ...
- JavaScript之链式结构序列化
一.概述 在JavaScript中,链式模式代码,太多太多,如下: if_else: if(...){ //TODO }else if(...){ //TODO }else{ //TODO } swi ...
- 算法与数据结构(十一) 平衡二叉树(AVL树)
今天的博客是在上一篇博客的基础上进行的延伸.上一篇博客我们主要聊了二叉排序树,详情请戳<二叉排序树的查找.插入与删除>.本篇博客我们就在二叉排序树的基础上来聊聊平衡二叉树,也叫AVL树,A ...
- Windows 常用运行库下载 (DirectX、VC++、.Net Framework等)
经常听到有朋友抱怨他的电脑运行软件或者游戏时提示缺少什么 d3dx9_xx.dll 或 msvcp71.dll.msvcr71.dll又或者是 .Net Framework 初始化之类的错误而无法正常 ...
- JavaWeb——Servlet
一.基本概念 Servlet是运行在Web服务器上的小程序,通过http协议和客户端进行交互. 这里的客户端一般为浏览器,发送http请求(request)给服务器(如Tomcat).服务器接收到请求 ...
- 【iOS】Xcode8+Swift3 纯代码模式实现 UICollectionView
开发环境 macOS Sierra 10.12.Xcode 8.0,如下图所示: 总体思路 1.建立空白的storyboard用于呈现列表 2.实现自定义单个单元格(继承自:UICollectionV ...
- 机器指令翻译成 JavaScript —— No.7 过渡语言
上一篇,我们决定使用 LLVM 来优化程序,并打算用 C 作为输入语言.现在我们来研究一下,将 6502 指令转换成 C 的可行性. 跳转支持 翻译成 C 语言,可比 JS 容易多了.因为 C 支持 ...