Https java信任_java在访问https资源时,忽略证书信任问题 (转)

当Java程序访问HTTPS资源遇到证书信任异常时,可以通过忽略证书验证或者导入证书到JDK信任列表来解决。忽略证书验证的代码实现包括自定义HostnameVerifier和TrustManager,允许所有证书。这种方法适用于测试环境,但在生产环境中需谨慎处理证书安全。

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服务器通信时有以下几个步骤,如图所示。

客户使用https的URL访问Web服务器,要求与Web服务器建立SSL连接。

Web服务器收到客户端请求后,会将网站的证书信息(证书中包含公钥)传送一份给客户端。

客户端的浏览器与Web服务器开始协商SSL连接的安全等级,也就是信息加密的等级。

客户端的浏览器根据双方同意的安全等级,建立会话密钥,然后利用网站的公钥将会话密钥加密,并传送给网站。

Web服务器利用自己的私钥解密出会话密钥。

Web服务器利用会话密钥加密与客户端之间的通信。

e19717a0e859834436b9424a997c596d.png

2)java程序的证书信任规则

如上文所述,客户端会从服务端拿到证书信息。调用端(客户端)会有一个证书信任列表,拿到证书信息后,会判断该证书是否可信任。

如果是用浏览器访问https资源,发现证书不可信任,一般会弹框告诉用户,对方的证书不可信任,是否继续之类。

Java虚拟机并不直接使用操作系统的keyring,而是有自己的security manager。与操作系统类似,jdk的security manager默认有一堆的根证书信任。如果你的https站点证书是花钱申请的,被这些根证书所信任,那使用java来访问此https站点会非常方便。因此,如果用java访问https资源,发现证书不可信任,则会报文章开头说到的错误。

解决问题的方法

将证书导入到jdk的信任证书中(理论上应该可行,未验证)

在客户端(调用端)添加逻辑,忽略证书信任问题

第一种方法,需要在每台运行该java程序的机器上,都做导入操作,不方便部署,因此,采用第二种方法。下面贴下该方法对应的代码。

验证可行的代码

1)先实现验证方法

HostnameVerifier hv = newHostnameVerifier() {publicboolean verify(String urlHostName, SSLSession session) {

System.out.println("Warning: URL Host:" + urlHostName + "vs."

+session.getPeerHost());return true;

}

};private static voidtrustAllHttpsCertificates() throws Exception {

javax.net.ssl.TrustManager[] trustAllCerts= new javax.net.ssl.TrustManager[1];

javax.net.ssl.TrustManager tm= newmiTM();

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 classmiTM implements javax.net.ssl.TrustManager,

javax.net.ssl.X509TrustManager {publicjava.security.cert.X509Certificate[] getAcceptedIssuers() {return null;

}publicboolean isServerTrusted(

java.security.cert.X509Certificate[] certs) {return true;

}publicboolean isClientTrusted(

java.security.cert.X509Certificate[] certs) {return true;

}public voidcheckServerTrusted(

java.security.cert.X509Certificate[] certs, String authType)

throws java.security.cert.CertificateException {return;

}public voidcheckClientTrusted(

java.security.cert.X509Certificate[] certs, String authType)

throws java.security.cert.CertificateException {return;

}

}

2)在访问https资源前,调用

trustAllHttpsCertificates();

HttpsURLConnection.setDefaultHostnameVerifier(hv);

参考文档(本文其实是将这三篇文章中,相关的内容整合到一起):

http://blog.csdn.net/mingli198611/article/details/8055261《HTTP和HTTPS详解》

http://www.cnblogs.com/wupher/archive/2012/08/05/2623561.html《使用Keytool为JDK添加https证书信任》

http://mengyang.iteye.com/blog/575671《解决PKIX path building failed的问题》

原文链接:https://blog.csdn.net/lizeyang/article/details/18983843

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值