您好,登錄后才能下訂單哦!
為了確保數(shù)據(jù)傳輸?shù)陌踩?,現(xiàn)在越來(lái)越多的應(yīng)用使用Https的方式來(lái)進(jìn)行數(shù)據(jù)傳輸,使用https有很多有點(diǎn),比如:
但是即使使用HTTPS有很多有點(diǎn),但是購(gòu)買一個(gè)認(rèn)證的HTTPS證書(shū)卻價(jià)格不菲,增加了初創(chuàng)企業(yè)和小團(tuán)隊(duì)的開(kāi)發(fā)成本。而且如上面所說(shuō),使用HTTPS并非絕對(duì)的安全,傳輸?shù)臄?shù)據(jù)并非沒(méi)有辦法獲取到,我的之前一篇博客所使用的方法已成功截取HTTPS的數(shù)據(jù)傳輸。有興趣的可以參考:使用Charles對(duì)Android App的https請(qǐng)求進(jìn)行抓包。
為了節(jié)約成本,我們可以選擇使用自簽名的HTTPS。
這種方式我們可以自己生成證書(shū),不需要購(gòu)買證書(shū),但是使用這種方式的域名如果在瀏覽器中訪問(wèn)的話,會(huì)有一個(gè)不安全的標(biāo)識(shí)。但是如果用在客戶端上,就不會(huì)有這個(gè)問(wèn)題,現(xiàn)在一些應(yīng)用商店也要求APP上架時(shí)需要使用HTTPS的網(wǎng)絡(luò)請(qǐng)求(比如AppStore),使用這種自簽名的HTTPS同樣也能過(guò)審。
本文我們介紹在Android上使用網(wǎng)絡(luò)請(qǐng)求框架Retrofit 2來(lái)請(qǐng)求自簽名的API,關(guān)于如何生成HTTPS證書(shū),我們將在另一篇博客中進(jìn)行說(shuō)明,敬請(qǐng)期待?;蛘吣梢宰孕胁檎蚁嚓P(guān)資料。
比如我們生成的SLL證書(shū)文件為"api_ssl_debug.cer",我們將其放到assets目錄下。這樣在配置Retrofit的時(shí)候就可以讀取該證書(shū)并用于API請(qǐng)求中。
本節(jié)我們介紹SSL證書(shū)在Retrofit中的配置,首先我們要定義兩個(gè)方法用來(lái)讀取證書(shū),然后講該證書(shū)用于Retrofit中。
private static KeyStore getKeyStore(String fileName) {
KeyStore keyStore = null;
try {
AssetManager assetManager = Utils.getApp().getAssets();
CertificateFactory cf = CertificateFactory.getInstance("X.509");
InputStream caInput = assetManager.open(fileName);
Certificate ca;
try {
ca = cf.generateCertificate(caInput);
Log.d("SslUtils", "ca=" + ((X509Certificate) ca).getSubjectDN());
} finally {
caInput.close();
}
String keyStoreType = KeyStore.getDefaultType();
keyStore = KeyStore.getInstance(keyStoreType);
keyStore.load(null, null);
keyStore.setCertificateEntry("ca", ca);
} catch (Exception e) {
Log.e("SslUtils", "Error during getting keystore", e);
}
return keyStore;
}
public static SSLContext getSslContextForCertificateFile(String fileName) {
try {
KeyStore keyStore = SslUtils.getKeyStore(fileName);
SSLContext sslContext = SSLContext.getInstance("SSL");
TrustManagerFactory trustManagerFactory = TrustManagerFactory.getInstance(TrustManagerFactory.getDefaultAlgorithm());
trustManagerFactory.init(keyStore);
sslContext.init(null, trustManagerFactory.getTrustManagers(), new SecureRandom());
return sslContext;
} catch (Exception e) {
String msg = "Error during creating SslContext for certificate from assets";
Log.e("SslUtils", msg, e);
throw new RuntimeException(msg);
}
}
SSLContext sslContext = SslUtils.getSslContextForCertificateFile("api_ssl_debug.cer");
TrustManagerFactory trustManagerFactory = TrustManagerFactory.getInstance(
TrustManagerFactory.getDefaultAlgorithm());
trustManagerFactory.init((KeyStore) null);
TrustManager[] trustManagers = trustManagerFactory.getTrustManagers();
if (trustManagers.length != 1 || !(trustManagers[0] instanceof X509TrustManager)) {
throw new IllegalStateException("Unexpected default trust managers:"
+ Arrays.toString(trustManagers));
}
X509TrustManager trustManager = (X509TrustManager) trustManagers[0];
OkHttpClient.Builder builder = new OkHttpClient.Builder()
...
.sslSocketFactory(sslContext.getSocketFactory(), trustManager)
.hostnameVerifier((hostname, session) -> true)
...
mRetrofit = new Retrofit.Builder()
...
build();
以上的省略號(hào)為Retrofit的其它配置,可以根據(jù)工程需要進(jìn)行配置。
至此,使用Retrofit就可以進(jìn)行自簽名的HTTPS的網(wǎng)絡(luò)請(qǐng)求了,當(dāng)然,服務(wù)器端的API配置也需要進(jìn)行HTTPS的配置,我將在服務(wù)端相關(guān)的博客進(jìn)行介紹,還有一點(diǎn),如果請(qǐng)求的域名指定了端口,要將端口設(shè)置為443。如果沒(méi)有指定端口,請(qǐng)求時(shí)也會(huì)自動(dòng)走443端口。
本文原始地址,如有更多疑問(wèn),請(qǐng)參考我的其它Android相關(guān)博客:我的博客地址
免責(zé)聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉(zhuǎn)載和分享為主,文章觀點(diǎn)不代表本網(wǎng)站立場(chǎng),如果涉及侵權(quán)請(qǐng)聯(lián)系站長(zhǎng)郵箱:is@yisu.com進(jìn)行舉報(bào),并提供相關(guān)證據(jù),一經(jīng)查實(shí),將立刻刪除涉嫌侵權(quán)內(nèi)容。