import java.io.BufferedReader;
import java.io.InputStream;
import java.io.InputStreamReader;
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;
/**
* 通过自定义 TrustManager 来实现无根证书时访问 https
* @date 2013-8-29
* @file HttpsClient.java
*/
public class HttpsClient {
/**
* 测试 https
* @param args
*/
public static void main(String[] args) throws Exception {
// init https
HttpsClient.init();
URL url = new URL("https://www.12306.cn/mormhweb/");
url.openConnection();
InputStream in = url.openStream();
BufferedReader buf = new BufferedReader(new InputStreamReader(in));
String line = null;
while ((line = buf.readLine()) != null){
System.out.println(line);
}
buf.close();
in.close();
System.out.println("-- finished --");
}
/**
* 初始化
*/
public static void init() {
try {
SSLContext sslCtx = SSLContext.getInstance("TLS");
sslCtx.init(null, new TrustManager[]{new MyTrustManager()}, null);
SSLSocketFactory sslSocketFactory = sslCtx.getSocketFactory();
HttpsURLConnection.setDefaultSSLSocketFactory(sslSocketFactory);
HttpsURLConnection.setDefaultHostnameVerifier(new HostnameVerifier() {
@Override
public boolean verify(String hostname, SSLSession session) {
return true;
}
});
}
catch (Exception e) {
e.printStackTrace();
}
}
}
/**
* 默认信任服务端根证书
*/
class MyTrustManager implements X509TrustManager {
@Override
public void checkClientTrusted(X509Certificate[] chain, String authType)
throws CertificateException {
return;
}
@Override
public void checkServerTrusted(X509Certificate[] chain, String authType)
throws CertificateException {
return;
}
@Override
public X509Certificate[] getAcceptedIssuers() {
return null;
}
}
# 访问 https 时有两个问题需要注意
# 1. 客户端需要存在有效的根证书
相应的异常信息:
Caused by: sun.security.provider.certpath.SunCertPathBuilderException: unable to find valid certification path to requested target
at sun.security.provider.certpath.SunCertPathBuilder.engineBuild(SunCertPathBuilder.java:196)
at java.security.cert.CertPathBuilder.build(CertPathBuilder.java:268)
at sun.security.validator.PKIXValidator.doBuild(PKIXValidator.java:380)
... 19 more
处理方法:
HttpsURLConnection.setDefaultSSLSocketFactory(sslSocketFactory);
# 2. 访问 https 时的域名需要与根证书中声明的域名一致
相应的异常信息:
Caused by: java.security.cert.CertificateException: No name matching www.12306.cn found
at sun.security.util.HostnameChecker.matchDNS(HostnameChecker.java:208)
at sun.security.util.HostnameChecker.match(HostnameChecker.java:93)
at sun.security.ssl.X509TrustManagerImpl.checkIdentity(X509TrustManagerImpl.java:347)
at sun.security.ssl.AbstractTrustManagerWrapper.checkAdditionalTrust(SSLContextImpl.java:847)
at sun.security.ssl.AbstractTrustManagerWrapper.checkServerTrusted(SSLContextImpl.java:814)
at sun.security.ssl.ClientHandshaker.serverCertificate(ClientHandshaker.java:1320)
... 13 more
处理方法:
HttpsURLConnection.setDefaultHostnameVerifier(new HostnameVerifier() {
@Override
public boolean verify(String hostname, SSLSession session) {
return true;
}
});
# 相关链接
http://wenku.baidu.com/view/ce0f191852d380eb62946d6a.html
http://blog.csdn.net/faye0412/article/details/6883879