package com.lzy.tool
;
import java.net.HttpURLConnection
;
import java.net.URL
;
import java.security.cert.CertificateException
;
import java.security.cert.X509Certificate
;
import javax.net.ssl.HostnameVerifier
;
import javax.net.ssl.HttpsURLConnection
;
import javax.net.ssl.SSLContext
;
import javax.net.ssl.SSLSession
;
import javax.net.ssl.SSLSocketFactory
;
import javax.net.ssl.TrustManager
;
import javax.net.ssl.X509TrustManager
;
/**
* wflinzhiyong@163.com
* Created by lzy on 2016/4/14.
*/
public class ddd {
public void Test(String str)
throws Exception {
URL url =
new URL(str)
;
HttpURLConnection connection = (HttpURLConnection) url.openConnection()
;
SSLSocketFactory oldSocketFactory =
null;
HostnameVerifier oldHostnameVerifier =
null;
boolean useHttps = str.startsWith(
"https")
;
if (useHttps) {
HttpsURLConnection https = (HttpsURLConnection) connection
;
oldSocketFactory =
trustAllHosts(https)
;
oldHostnameVerifier = https.getHostnameVerifier()
;
https.setHostnameVerifier(
DO_NOT_VERIFY)
;
}
}
/**
* 覆盖java默认的证书验证
*/
private static final TrustManager[]
trustAllCerts =
new TrustManager[]{
new X509TrustManager() {
public java.security.cert.X509Certificate[]
getAcceptedIssuers() {
return new java.security.cert.X509Certificate[]{}
;
}
public void checkClientTrusted(X509Certificate[] chain
, String authType)
throws CertificateException {
}
public void checkServerTrusted(X509Certificate[] chain
, String authType)
throws CertificateException {
}
}}
;
/**
* 设置不验证主机
*/
private static final HostnameVerifier
DO_NOT_VERIFY =
new HostnameVerifier() {
public boolean verify(String hostname
, SSLSession session) {
return true;
}
}
;
/**
* 信任所有
* @param connection
* @return
*/
private static SSLSocketFactory
trustAllHosts(HttpsURLConnection connection) {
SSLSocketFactory oldFactory = connection.getSSLSocketFactory()
;
try {
SSLContext sc = SSLContext.
getInstance(
"TLS")
;
sc.
init(
null, trustAllCerts, new java.security.SecureRandom())
;
SSLSocketFactory newFactory = sc.getSocketFactory()
;
connection.setSSLSocketFactory(newFactory)
;
}
catch (Exception e) {
e.printStackTrace()
;
}
return oldFactory
;
}
}
X509证书信任管理器类的详解
在JSSE中,证书信任管理器类就是实现了接口X509TrustManager的类。我们可以自己实现该接口,让它信任我们指定的证书。 接口X509TrustManager有下述三个公有的方法需要我们实现: ⑴ oid checkClientTrusted(X509Certificate[] chain, String authType) throws CertificateException 该方法检查客户端的证书,若不信任该证书则抛出异常。由于我们不需要对客户端进行认证,因此我们只需要执行默认的信任管理器的这个方法。JSSE中,默认的信任管理器类为TrustManager。 ⑵ oid checkServerTrusted(X509Certificate[] chain, String authType) throws CertificateException 该方法检查服务器的证书,若不信任该证书同样抛出异常。通过自己实现该方法,可以使之信任我们指定的任何证书。在实现该方法时,也可以简单的不做任何处理,即一个空的函数体,由于不会抛出异常,它就会信任任何证书。 ⑶ X509Certificate[] getAcceptedIssuers() 返回受信任的X509证书数组。 自己实现了信任管理器类,如何使用呢?类HttpsURLConnection似乎并没有提供方法设置信任管理器。其实,HttpsURLConnection通过SSLSocket来建立与HTTPS的安全连接,SSLSocket对象是由SSLSocketFactory生成的。HttpsURLConnection提供了方法setSSLSocketFactory(SSLSocketFactory)设置它使用的SSLSocketFactory对象。SSLSocketFactory通过SSLContext对象来获得,在初始化SSLContext对象时,可指定信任管理器对象。下面用一个图简单表示这几个JSSE类的关系: 图1 部分JSSE类的关系图 假设自己实现的X509TrustManager类的类名为:MyX509TrustManager,下面的代码片断说明了如何使用MyX509TrustManager: //创建SSLContext对象,并使用我们指定的信任管理器初始化 TrustManager[] tm = {new MyX509TrustManager ()}; SSLContext sslContext = SSLContext.getInstance("SSL","SunJSSE"); sslContext.init(null, tm, new java.security.SecureRandom()); //从上述SSLContext对象中得到SSLSocketFactory对象 SSLSocketFactory ssf = sslContext.getSocketFactory(); //创建HttpsURLConnection对象,并设置其SSLSocketFactory对象 HttpsURLConnection httpsConn = (HttpsURLConnection)myURL.openConnection(); httpsConn.setSSLSocketFactory(ssf); 这样,HttpsURLConnection对象就可以正常连接HTTPS了,无论其证书是否经权威机构的验证,只要实现了接口X509TrustManager的类MyX509TrustManager信任该证书。 小结 本文主要介绍了在HTTPS的证书未经权威机构认证的情况下,访问HTTPS站点的两种方法,一种方法是把该证书导入到Java的TrustStore文件中,另一种是自己实现并覆盖JSSE缺省的证书信任管理器类。两种方法各有优缺点,第一种方法不会影响JSSE的安全性,但需要手工导入证书;第二种方法虽然不用手工导入证书,但需要小心使用,否则会带来一些安全隐患。
转载请注明原文地址: https://ju.6miu.com/read-674608.html