Android HttpsURLConnection SSL验证
本文只针对Android端使用HttpsURLConnection进行SSL验证的情况,HttpClient及其它第三方成熟的网络请求框架的配置不在此介绍,https介绍及证书相关知识建议使用前详细查阅。
1、cer,crt证书使用
Google官方有示例(https://developer.android.com/training/articles/security-ssl.html)
将证书文件xx.cer或xx.crt 放到项目工程如raw、assets目录下,为了使用方便一般都放到raw目录下
核心代码:
CertificateFactory cf = CertificateFactory.getInstance("X.509");
InputStream caInput = context.getResources().openRawResource(R.raw.xx);
Certificate ca;
try {
ca = cf.generateCertificate(caInput);
} finally {
caInput.close();
}
String keyStoreType = KeyStore.getDefaultType();
KeyStore keyStore = KeyStore.getInstance(keyStoreType);
keyStore.load(null, null);
keyStore.setCertificateEntry("ca", ca);
String tmfAlgorithm = TrustManagerFactory.getDefaultAlgorithm();
TrustManagerFactory tmf = TrustManagerFactory.getInstance(tmfAlgorithm);
tmf.init(keyStore);
SSLContext context = SSLContext.getInstance("TLS");
context.init(null, tmf.getTrustManagers(), null);
urlConnection = (HttpsURLConnection) url.openConnection();
((HttpsURLConnection) urlConnection).setSSLSocketFactory(context.getSocketFactory());
((HttpsURLConnection) urlConnection).setHostnameVerifier(new HostnameVerifier() {
@Override
public boolean verify(String hostname, SSLSession session) {
return true;
}
});
2、bks格式证书使用
同样将证书文件xx.bks 放到项目工程raw目录下
核心代码:
KeyStore ks = KeyStore.getInstance("BKS");
InputStream stream = context.getResources().openRawResource(R.raw.xx);
ks.load(stream, null);
stream.close();
TrustManagerFactory trustManagerFactory = TrustManagerFactory.getInstance(TrustManagerFactory.getDefaultAlgorithm());
trustManagerFactory.init(ks);
SSLContext sc = SSLContext.getInstance("TLS");
sc.init(null, trustManagerFactory.getTrustManagers(), null);
urlConnection = (HttpsURLConnection) url.openConnection();
((HttpsURLConnection) urlConnection).setSSLSocketFactory(sc.getSocketFactory());
((HttpsURLConnection) urlConnection).setHostnameVerifier(new HostnameVerifier() {
@Override
public boolean verify(String hostname, SSLSession session) {
return true;
}
});
但是,大部分情况下得到的可能是 JKS 格式或者是 CRT CER文件,如果要转成BKS使用,下面介绍方法。
去http://bouncycastle.org/latest_releases.html下载支持BKS格式转换的jar包,使用keytool工具转换,命令如下:
keytool -importcert -v -trustcacerts -file "path_to_cert/xx.cer" -alias xx -keystore "path_to_your/xx.bks"
-provider org.bouncycastle.jce.provider.BouncyCastleProvider -providerpath "path_to_bouncycastle/bcprov-jdk16-145.jar"
-storetype BKS -storepass password
另外GUI工具KeyStore Explorer也支持转换
使用异常
java.io.IOException: Hostname 'xx.com' was not verified
可能是服务器配置不全有识或者用虚拟主机导致,实际上正式使用时一般会加上一个customHostnameVerifier,加上下划线代码可解决,但比较暴力。
javax.net.ssl.SSLHandshakeException: javax.net.ssl.SSLProtocolException: SSL handshake aborted: ssl=0x63e562b0: Failure in SSL library, usually a protocol error
此异常发生笔者碰到过两种情况,一种原因是服务端HTTPS配置不支持SSLv3,在Android sdk4.4以下版本里建立安全连接时协议版本从TLSv1回落到SSLv3,解决方法
另外一种比较诡异,在没有给urlConnection对象调用setHostnameVerifier方法时也抛出了此异常,设置hostnameVerifier后正常。
有误请指正,转载请标明出处。

浙公网安备 33010602011771号