本文只针对Android端使用HttpsURLConnection进行SSL验证的状况,HttpClient及其它第三方成熟的网络请求框架的配置不在此介绍,https介绍及证书相关知识建议使用前详细查阅。html
Google官方有示例(https://developer.android.com/training/articles/security-ssl.html)java
将证书文件xx.cer或xx.crt 放到项目工程如raw、assets目录下,为了使用方便通常都放到raw目录下android
核心代码:安全
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; } });
一样将证书文件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使用,下面介绍方法。session
去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"ide
-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后正常。
有误请指正,转载请标明出处。