本文只針對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後正常。
有誤請指正,轉載請標明出處。