java在访问https资源时,忽略证书信任问题

标签: java 访问 https | 发表时间:2014-02-08 21:19 | 作者:lizeyang
出处:http://blog.csdn.net
java程序在访问https资源时,出现报错
sun.security.validator.ValidatorException: PKIX path building failed: sun.security.provider.certpath.SunCertPathBuilderException: unable to find valid certification path to requested target
这本质上,是java在访问https资源时的证书信任问题。如何解决这个问题呢?

为何有这个问题?
解决这个问题前,要了解
1)https通信过程
客户端在使用HTTPS方式与Web服务器通信时有以下几个步骤,如图所示。
(1)客户使用https的URL访问Web服务器,要求与Web服务器建立SSL连接。
(2)Web服务器收到客户端请求后,会将网站的证书信息(证书中包含公钥)传送一份给客户端。
(3)客户端的浏览器与Web服务器开始协商SSL连接的安全等级,也就是信息加密的等级。
(4)客户端的浏览器根据双方同意的安全等级,建立会话密钥,然后利用网站的公钥将会话密钥加密,并传送给网站。
(5)Web服务器利用自己的私钥解密出会话密钥。
(6)Web服务器利用会话密钥加密与客户端之间的通信。



2)java程序的证书信任规则
如上文所述,客户端会从服务端拿到证书信息。调用端(客户端)会有一个证书信任列表,拿到证书信息后,会判断该证书是否可信任。
如果是用浏览器访问https资源,发现证书不可信任,一般会弹框告诉用户,对方的证书不可信任,是否继续之类。
Java虚拟机并不直接使用操作系统的keyring,而是有自己的security manager。与操作系统类似,jdk的security manager默认有一堆的根证书信任。如果你的https站点证书是花钱申请的,被这些根证书所信任,那使用java来访问此https站点会非常方便。因此,如果用java访问https资源,发现证书不可信任,则会报文章开头说到的错误。

解决问题的方法
1)将证书导入到jdk的信任证书中(理论上应该可行,未验证)
2)在客户端(调用端)添加逻辑,忽略证书信任问题
第一种方法,需要在每台运行该java程序的机器上,都做导入操作,不方便部署,因此,采用第二种方法。下面贴下该方法对应的代码。

验证可行的代码
1)先实现验证方法
HostnameVerifier hv = new HostnameVerifier() {
        public boolean verify(String urlHostName, SSLSession session) {
            System.out.println("Warning: URL Host: " + urlHostName + " vs. "
                               + session.getPeerHost());
            return true;
        }
    };
 
 private static void trustAllHttpsCertificates() throws Exception {
 javax.net.ssl.TrustManager[] trustAllCerts = new javax.net.ssl.TrustManager[1];
 javax.net.ssl.TrustManager tm = new miTM();
 trustAllCerts[0] = tm;
 javax.net.ssl.SSLContext sc = javax.net.ssl.SSLContext
 .getInstance("SSL");
 sc.init(null, trustAllCerts, null);
 javax.net.ssl.HttpsURLConnection.setDefaultSSLSocketFactory(sc
 .getSocketFactory());
 }

 static class miTM implements javax.net.ssl.TrustManager,
 javax.net.ssl.X509TrustManager {
 public java.security.cert.X509Certificate[] getAcceptedIssuers() {
 return null;
 }

 public boolean isServerTrusted(
 java.security.cert.X509Certificate[] certs) {
 return true;
 }

 public boolean isClientTrusted(
 java.security.cert.X509Certificate[] certs) {
 return true;
 }

 public void checkServerTrusted(
 java.security.cert.X509Certificate[] certs, String authType)
 throws java.security.cert.CertificateException {
 return;
 }

 public void checkClientTrusted(
 java.security.cert.X509Certificate[] certs, String authType)
 throws java.security.cert.CertificateException {
 return;
 }
 }
2)在访问https资源前,调用
trustAllHttpsCertificates();
HttpsURLConnection.setDefaultHostnameVerifier(hv);


参考文档(本文其实是将这三篇文章中,相关的内容整合到一起):
http://www.cnblogs.com/wupher/archive/2012/08/05/2623561.html《使用Keytool为JDK添加https证书信任》
http://mengyang.iteye.com/blog/575671《解决PKIX path building failed的问题》
作者:lizeyang 发表于2014-2-8 13:19:09 原文链接
阅读:37 评论:0 查看评论

相关 [java 访问 https] 推荐:

java在访问https资源时,忽略证书信任问题

- - CSDN博客推荐文章
java程序在访问https资源时,出现报错. 这本质上,是java在访问https资源时的证书信任问题. 客户端在使用HTTPS方式与Web服务器通信时有以下几个步骤,如图所示. (1)客户使用https的URL访问Web服务器,要求与Web服务器建立SSL连接. (2)Web服务器收到客户端请求后,会将网站的证书信息(证书中包含公钥)传送一份给客户端.

nginx强制使用https访问的多种方法(http跳转到https)

- - C1G军火库
nginx强制使用https访问的多种方法(http跳转到https). 先说明一下HTTP跳转的状态码. 301 Moved Permanently:该方式将所有的 HTTP 请求重定向到 HTTPS 上,并且该重定向是永久性的. 客户端在收到 301 响应后,会自动将 HTTP 请求转为 GET 请求,同时将请求地址修改为重定向后的地址.

Elasticsearch:在 Java 客户端中使用 truststore 来创建 HTTPS 连接

- - 掘金 后端
在我之前的文章 “ Elasticsearch:使用 Elasticsearch Java client 8.0 来连接带有 HTTPS 的集群” 里,我使用了两种方法,一直是使用 token 的方式,另外一种是使用 PEM 证书来进行连接的. 在实际的使用中,有时我们的证书是以 PCKS12 格式的 truststore 格式的,那么我们该如何建立这种 HTTPS 的连接呢.

强制Chrome浏览器Https加密访问网站

- HENG - 启光博客
  强制Chrome浏览器加密访问网站其实也就是强制Chrome浏览器http重定向到https,这种技巧对于经常修改Hosts的网友可能用处较大些. 比如修改Hosts后访问Twitter,多数情况下访问http://www.twitter.com是不能访问的,要输入https://twitter.com才行.

维基百科启用 HTTPS 访问支持

- 万俟尘 - #ifanrlive
维基百科(Wikipedia)发布博文称已启用原生 HTTPS 访问支持. “这允许您访问我们的网站,而不必跟踪您的浏览习惯;您可以无需担心您的密码或用户会话数据被盗而直接登录访问. ”维基百科的运营工程师 Ryan Lane 在博文里这样写道. 维基百科公布了 HTTPS 的具体配置,并强调相比此前的安全网址“HTTPS 能够带来更安全的浏览”.

certbot在Centos7上配置合法签名证书,实现nginx的https访问-咖啡猫Mr-51CTO博客

- -
  公司因之前使用的openssh创建的自签名证书,有一个弊端,就是在某些客户端上不能使用此证书,无法使用https连接,所以,研究了一下certbot 做签名证书. 你需要有一个公网地址,并绑定合法域名. (1)、下载Certbot客户端:. (2)、下载后,进入下载的目录,添加执行权限. 3、介绍一下certbot的两种工作方式:.

https协议

- - 互联网 - ITeye博客
SSL 协议的握手过程   .       为了便于更好的认识和理解 SSL 协议,这里着重介绍 SSL 协议的握手协议. SSL 协议既用到了公钥加密技术(非对称加密)又用到了对称加密技术,SSL对传输内容的加密是采用的对称加密,然后对对称加密的密钥使用公钥进行非对称加密. 这样做的好处是,对称加密技术比公钥加密技术的速度快,可用来加密较大的传输内容,公钥加密技术相对较慢,提供了更好的身份认证技术,可用来加密对称加密过程使用的密钥.

Go和HTTPS

- - Tony Bai
近期在构思一个产品,考虑到安全性的原因,可能需要使用到 HTTPS协议以及双向数字证书校验. 之前只是粗浅接触过HTTP( 使用Golang开 发微信系列). 对HTTPS的了解则始于那次 自行搭建ngrok服务,在那个过程中照猫画虎地为服务端生成了一些私钥和证书,虽然结果是好 的:ngrok服务成功搭建起来了,但对HTTPS、数字证书等的基本原理并未求甚解.

怎样实现Java远程访问Domino数据库

- - 数据库 - ITeye博客
Java远程访问Domino数据库推荐采用CORBA实现,但配置非常关键,笔者在工作中也遇到了这个问题,在查阅资料的过程中发现,很多文章明显存在一些误区或者说没有写清楚的地方,现将笔者的实践经验总结出来,和大家分享. Domino服务器版本是5.0.9.   1.修改Domino服务器安全性配置,允许你的用户运行Java/CORBA.

Uncode-DAL 2.0.0 发布,Java 通用数据访问层

- - 开源中国社区最新新闻
Uncode-DAL 是 Java 通用数据访问组件,基于mybatis、spring jdbc、hibernate、mongo等ORM框架开发,同时支持基于多数据源的读写分离、主备切换、故障转移,自动恢复、负载均衡、缓存等. Uncode-DAL 2.0.0 大版本发布,截止现在基本完成计划开发功能.