1. 前言
HTTPS越來越成為主流,谷歌從 2017 年起,Chrome 瀏覽器將也會把采用 HTTP 協議的網站標記為「不安全」網站;蘋果從 2017 年 iOS App 將強制使用 HTTPS;在國內熱火朝天的小程序也要求必須使用 HTTPS 請求。那么為什么要使用HTTPS呢?首先說為什么使用https,簡單點說就是為了防止數據傳輸過程中信息被竊取或偷換,防止中間人攻擊。

2. 准備BKS證書,將證書放到項目raw目錄下
准備.cer文件
可以跟后台開發人員直接拿,也可以直接在網站上下載
在網站上下載:
點擊地址欄前面的小鎖頭,然后點擊證書信息








將.cer轉換為.bks
首先要下載bouncycastle的JAR
http://repo2.maven.org/maven2/org/bouncycastle/bcprov-jdk16/1.46/bcprov-jdk16-1.46.jar
解壓后在當前文件夾執行以下命令
keytool -importcert -v -trustcacerts -file “server.cert” -alias server_alias -keystore “server.bks” -provider org.bouncycastle.jce.provider.BouncyCastleProvider -providerpath “bcprov-jdk16-146.jar” -storetype BKS -storepass password
黑體字部分是你要修改的,其中 “server.cert”是原cer證書的名字,“server_alias”是別名,“server.bks”是轉換后bks證書的名字,“password”是你證書的密碼,下邊會用到的。
成功后將.bks證書文件放到項目的raw目錄下。
3. 獲取SSLSocketFactory
這里是HTTPS證書認證的關鍵代碼,注意password和設置keystore的bks類型一定不要搞錯。
/**
* 獲取bks文件的sslsocketfactory
* @param context
* @return
*/
public static SSLSocketFactory getSSLSocketFactory(Context context) {
final String CLIENT_TRUST_PASSWORD = "123456";//信任證書密碼,該證書默認密碼是123456
final String CLIENT_AGREEMENT = "TLS";//使用協議
final String CLIENT_TRUST_KEYSTORE = "BKS";
SSLContext sslContext = null;
try {
//取得SSL的SSLContext實例
sslContext = SSLContext.getInstance(CLIENT_AGREEMENT);
//取得TrustManagerFactory的X509密鑰管理器實例
TrustManagerFactory trustManager = TrustManagerFactory.getInstance(TrustManagerFactory.getDefaultAlgorithm());
//取得BKS密庫實例
KeyStore tks = KeyStore.getInstance(CLIENT_TRUST_KEYSTORE);
InputStream is = context.getResources().openRawResource(R.raw.traint);
try {
tks.load(is, CLIENT_TRUST_PASSWORD.toCharArray());
} finally {
is.close();
}
//初始化密鑰管理器
trustManager.init(tks);
//初始化SSLContext
sslContext.init(null, trustManager.getTrustManagers(), null);
} catch (Exception e) {
e.printStackTrace();
Log.e("SslContextFactory", e.getMessage());
}
return sslContext.getSocketFactory();
}
4.配置retrofit
String baseUrl = "https://skyish-test.yunext.com";
int[] certificates = {R.raw.traint};
String[] hostUrls = {baseUrl};
OkHttpClient client = new okhttp3.OkHttpClient.Builder()
.addInterceptor(new HttpLoggingInterceptor().setLevel(HttpLoggingInterceptor.Level.BODY))
.sslSocketFactory(HTTPSUtils.getSSLSocketFactory(context))
//.hostnameVerifier(HTTPSUtils.getHostNameVerifier(hostUrls))
.readTimeout(10, TimeUnit.SECONDS)
.connectTimeout(10, TimeUnit.SECONDS)
.build();
Retrofit retrofit = new Retrofit.Builder().baseUrl(baseUrl)
.addConverterFactory(GsonConverterFactory.create())
.addCallAdapterFactory(RxJavaCallAdapterFactory.create())
.client(client)
.build();
配置好這個就可以使用HTTPS連接了。
5.常見錯誤
SSLContext is not initialized.

原因:
1. 證書和證書密碼不匹配。
2. 使用了錯誤的證書。證書類型不對,記得要用bks格式的證書文件。
