1.Https相關(guān)知識
1.1 http與https的區(qū)別
HTTP協(xié)議傳輸?shù)臄?shù)據(jù)都是未加密的,也就是明文的,因此使用HTTP協(xié)議傳輸隱私信息非常不安全,為了保證這些隱私數(shù)據(jù)能加密傳輸,于是網(wǎng)景公司設(shè)計了SSL(Secure Sockets Layer)協(xié)議用于對HTTP協(xié)議傳輸?shù)臄?shù)據(jù)進(jìn)行加密,從而就誕生了HTTPS。簡單來說,HTTPS協(xié)議是由SSL+HTTP協(xié)議構(gòu)建的可進(jìn)行加密傳輸、身份認(rèn)證的網(wǎng)絡(luò)協(xié)議,要比http協(xié)議安全。
HTTPS和HTTP的區(qū)別主要如下:
- https協(xié)議需要到ca申請證書,一般免費(fèi)證書較少,因而需要一定費(fèi)用。
- http是超文本傳輸協(xié)議,信息是明文傳輸,https則是具有安全性的ssl加密傳輸協(xié)議。
- http和https使用的是完全不同的連接方式,用的端口也不一樣,前者是80,后者是443。
- http的連接很簡單,是無狀態(tài)的;HTTPS協(xié)議是由SSL+HTTP協(xié)議構(gòu)建的可進(jìn)行加密傳輸、身份認(rèn)證的網(wǎng)絡(luò)協(xié)議,比http協(xié)議安全。
1.2 Https的優(yōu)點(diǎn)
- 認(rèn)證用戶和服務(wù)器,確保數(shù)據(jù)發(fā)送到正確的客戶機(jī)和服務(wù)器;(驗(yàn)證證書)
- 加密數(shù)據(jù)以防止數(shù)據(jù)中途被竊??;(加密)
- 維護(hù)數(shù)據(jù)的完整性,確保數(shù)據(jù)在傳輸過程中不被改變。(摘要算法)
2.Okhttp中使用自簽名證書
一般支持https的網(wǎng)站,都是CA(Certificate Authority)機(jī)構(gòu)頒發(fā)的證書,但是一般該機(jī)構(gòu)頒發(fā)的證書需要提供費(fèi)用且有使用時間的限制,到期需要續(xù)費(fèi)。否則默認(rèn)該鏈接是不信任的,通過okHttp無法直接訪問。
但是我們可以使用自簽的方式,通過JDK自帶的keytool.exe 生成一個自己的證書,然后使用該證書內(nèi)容。雖然也是會出現(xiàn)提示“不安全”,但是我們可以通過okhttp訪問鏈接。
2.1 使用自簽證書
將證書文件放置在assets目錄(也可以放置在其他目錄下,只要能正確讀取到該文件),在創(chuàng)建OkhttpClient對象時sslSocketFactory()將該證書信息添加。
private SSLContext getSLLContext() {
SSLContext sslContext = null;
try {
CertificateFactory certificateFactory = CertificateFactory.getInstance("X.509");
InputStream certificate = mContext.getAssets().open("gdroot-g2.crt");
KeyStore keyStore = KeyStore.getInstance(KeyStore.getDefaultType());
keyStore.load(null);
String certificateAlias = Integer.toString(0);
keyStore.setCertificateEntry(certificateAlias, certificateFactory.generateCertificate(certificate));
sslContext = SSLContext.getInstance("TLS");
final TrustManagerFactory trustManagerFactory = TrustManagerFactory.getInstance(TrustManagerFactory.getDefaultAlgorithm());
trustManagerFactory.init(keyStore);
sslContext.init(null, trustManagerFactory.getTrustManagers(), new SecureRandom());
} catch (CertificateException e) {
e.printStackTrace();
} catch (KeyStoreException e) {
e.printStackTrace();
} catch (NoSuchAlgorithmException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
} catch (KeyManagementException e) {
e.printStackTrace();
}
return sslContext;
}
通過以上代碼可以看出,通過InputStream方式讀取證書信息,因此為了避免將證書文件打包到APK中,我們可以直接將證書文件內(nèi)容放置在String中,將該字符串轉(zhuǎn)為流的形式。
在使用okhttp時,將其設(shè)置到sslSocketFactory中。
OkHttpClient httpClient = new OkHttpClient().newBuilder()
.sslSocketFactory(getSLLContext().getSocketFactory())
.build();
2.2 信任所有證書
通過添加證書的形式,可以實(shí)現(xiàn)客戶端訪問Https服務(wù)端的功能,但是如果服務(wù)端更換證書內(nèi)容,那么客戶端需要相應(yīng)的更換https證書,否則無法正常交互獲取不到數(shù)據(jù),我們可以通過自定義X509TrustManager的形式實(shí)現(xiàn)來規(guī)避所有的證書檢測,實(shí)現(xiàn)信任所有證書的目的。
private OkHttpClient getHttpsClient() {
OkHttpClient.Builder okhttpClient = new OkHttpClient().newBuilder();
//信任所有服務(wù)器地址
okhttpClient.hostnameVerifier(new HostnameVerifier() {
@Override
public boolean verify(String s, SSLSession sslSession) {
//設(shè)置為true
return true;
}
});
//創(chuàng)建管理器
TrustManager[] trustAllCerts = new TrustManager[] { new X509TrustManager() {
@Override
public void checkClientTrusted(
java.security.cert.X509Certificate[] x509Certificates,
String s) throws java.security.cert.CertificateException {
}
@Override
public void checkServerTrusted(
java.security.cert.X509Certificate[] x509Certificates,
String s) throws java.security.cert.CertificateException {
}
@Override
public java.security.cert.X509Certificate[] getAcceptedIssuers() {
return new java.security.cert.X509Certificate[] {};
}
} };
try {
SSLContext sslContext = SSLContext.getInstance("TLS");
sslContext.init(null, trustAllCerts, new java.security.SecureRandom());
//為OkHttpClient設(shè)置sslSocketFactory
okhttpClient.sslSocketFactory(sslContext.getSocketFactory());
} catch (Exception e) {
e.printStackTrace();
}
return okhttpClient.build();
}
創(chuàng)建X509TrustManager對象,并實(shí)現(xiàn)其中的方法,由于X509TrustManager是通用證書格式,只需要拿到該格式就行。最后init該安全協(xié)議,將其放入okhttp的sslSocketFactory中。
由于Retrofit只是對Okhttp網(wǎng)絡(luò)接口的封裝,因此實(shí)際使用中,該方法同樣適用于Retrofit中。
歡迎關(guān)注曉涵說(CSDN)、xukang868(github)賬號信息,查看更多文章。