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后正常。

 

有误请指正,转载请标明出处。

 

posted @ 2016-09-13 20:34  ryn戈  阅读(6505)  评论(0)    收藏  举报