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 ...
随机推荐
- 设计爬虫Hawk背后的故事
本文写于圣诞节北京下午慵懒的午后.本文偏技术向,不过应该大部分人能看懂. 五年之痒 2016年,能记入个人年终总结的事情没几件,其中一个便是开源了Hawk.我花不少时间优化和推广它,得到的评价还算比较 ...
- Gradle 实现 Android 多渠道定制化打包
Gradle 实现 Android 多渠道定制化打包 版权声明:本文为博主原创文章,未经博主允许不得转载. 最近在项目中遇到需要实现 Apk 多渠道.定制化打包, Google .百度查找了一些资料, ...
- AFNetworking 3.0 源码解读(十)之 UIActivityIndicatorView/UIRefreshControl/UIImageView + AFNetworking
我们应该看到过很多类似这样的例子:某个控件拥有加载网络图片的能力.但这究竟是怎么做到的呢?看完这篇文章就明白了. 前言 这篇我们会介绍 AFNetworking 中的3个UIKit中的分类.UIAct ...
- AFNetworking 3.0 源码解读(九)之 AFNetworkActivityIndicatorManager
让我们的APP像艺术品一样优雅,开发工程师更像是一名匠人,不仅需要精湛的技艺,而且要有一颗匠心. 前言 AFNetworkActivityIndicatorManager 是对状态栏中网络激活那个小控 ...
- redis成长之路——(一)
为什么使用redis Redis适合所有数据in-momory的场景,虽然Redis也提供持久化功能,但实际更多的是一个disk-backed的功能,跟传统意义上的持久化有比较大的差别,那么可能大家就 ...
- Spring配置文件标签报错:The prefix "XXX" for element "XXX:XXX" is not bound. .
例如:The prefix "context" for element "context:annotation-config" is not bound. 这种 ...
- arcgis api for js入门开发系列四地图查询(含源代码)
备注:由于实现本篇功能的需求,修改了地图数据的dlsearch.mxd,然后更新了地图服务,需要的在文章最后有提供最新的mxd以及源代码下载的 上一篇实现了demo的地图工具栏,本篇新增地图查询功能, ...
- SQL 约束
先用设计器创建约束.再用代码创建约束.数据库约束是为了保证数据的完整性(正确性)而实现的一套机制见文件Employee.sql非空约束(选择复选框)主键约束(PK) primary key const ...
- sql 删除表中的重复记录
嗯,遇见了表中存在重复的记录的问题,直接写sql删除时最快的,才不要慢慢的复制到excel表中慢慢的人工找呢.哼. 如下sql,找出重复的记录,和重复记录中ID值最小的记录(表中ID为自增长) sel ...
- HP服务器 hp 360g5 centos7安装问题
HP服务器 hp 360g5 centos7安装问题 一 :启动盘无法识别硬盘 1.进入安装光盘,用上下键选择安装centos--Install Centos7(注意不可按Enter键),如图: 2 ...