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 ...
随机推荐
- 使用TSQL查询和更新 JSON 数据
JSON是一个非常流行的,用于数据交换的文本数据(textual data)格式,主要用于Web和移动应用程序中.JSON 使用“键/值对”(Key:Value pair)存储数据,能够表示嵌套键值对 ...
- [APUE]UNIX进程的环境(下)
一.共享库 共享库使得可执行文件中不再需要包含常用的库函数,而只需在所有进程都可存取的存储区中保存这种库例程的一个副本.程序第一次执行的时候或第一次调用某个库函数的时候,用动态链接方法将程序与共享库函 ...
- JAVA语言中的修饰符
JAVA语言中的修饰符 -----------------------------------------------01--------------------------------------- ...
- C# i=0;i=i++,i的值是多少?
昨天看群里dalao们聊天,有一个人出来问这个问题 这个题应该是挺常见的 int i = 0, t; for(t = 0;t <= 5;t++) { ...
- React使用antd Table生成层级多选组件
一.需求 用户对不同的应用需要有不同的权限,用户一般和角色关联在一起,新建角色的时候会选择该角色对应的应用,然后对应用分配权限.于是写了一种实现的方式.首先应用是一个二级树,一级表示的是应用分组,二级 ...
- 你真的会玩SQL吗?之逻辑查询处理阶段
你真的会玩SQL吗?系列目录 你真的会玩SQL吗?之逻辑查询处理阶段 你真的会玩SQL吗?和平大使 内连接.外连接 你真的会玩SQL吗?三范式.数据完整性 你真的会玩SQL吗?查询指定节点及其所有父节 ...
- Postman接口调试神器-Chrome浏览器插件
首先大家可以去这个地址下载 Postman_v4.1.3 这个版本,我用的就是这个版本 http://chromecj.com/web-development/2014-09/60/download. ...
- C# Entity Framework并发处理
原网站:C# Entity Framework并发处理 在软件开发过程中,并发控制是确保及时纠正由并发操作导致的错误的一种机制.从 ADO.NET 到 LINQ to SQL 再到如今的 ADO.NE ...
- iOS之计算上次日期距离现在多久, 如 xx 小时前、xx 分钟前等
/** * 计算上次日期距离现在多久 * * @param lastTime 上次日期(需要和格式对应) * @param format1 上次日期格式 * @para ...
- GSD_WeiXin(高仿微信)应用源码
高仿微信计划:已经实现功能 1.微信首页(cell侧滑编辑.下拉眼睛动画.下拉拍短视频.点击进入聊天详情界面) 2.通讯录(联系人字母排序.搜索界面) 3.发现(朋友圈) 4.我(界面) 待实现功能( ...