OkHttp盡力去平衡兩個相互競爭的關(guān)注點:
- Connectivity:盡可能地連接更多地主機缭乘。這個包括運行boringssl最新版本的先進主機和運行OpenSSL老版本的稍微過時的主機沐序。
- Security:連接的安全性。這個包括使用證書驗證遠程網(wǎng)絡(luò)服務(wù)器和使用強密碼的數(shù)據(jù)交換隱私堕绩。
當涉及到一個到HTTPS服務(wù)器的連接時策幼,OkHttp需要知道提供哪個TLS版本和安全套件。一個客戶端想要最大化連通性會包含廢棄的TLS版本和weak-by-design密碼套件奴紧。一個嚴謹?shù)目蛻舳讼胍畲蠡B通性會限制只能用最新TLS版本和最強的密碼套件掸犬。
特定的安全vs連通性決策通過ConnectionSpec實現(xiàn)用押。OkHttp包含三個內(nèi)置的連接規(guī)格:
- MODERN_TLS:一個連接先進HTTPS服務(wù)器的安全配置握巢。
- COMPATIBLE_TLS:一個連接安全但是非current-HTTPS服務(wù)器的安全配置彤路。
- CLEARTEXT:一個用于http://的URL的不安全配置。
默認沫浆,OkHttp會嘗試MODERN_TLS連接捷枯,如果先進配置失敗,則會回退到COMPATIBLE_TLS連接件缸。
TLS版本和加密套件的規(guī)格可能隨著每個版本改變铜靶。例如,在OkHttp2.2他炊,我們放棄支持SSL3.0作為POODLE攻擊的響應(yīng)。在OkHttp2.3放棄支持RC4.與你的桌面網(wǎng)絡(luò)瀏覽器一樣已艰,保持OkHttp最新是保持安全的最好方式痊末。
你可以使用一個自定義TLS版本和加密套件集構(gòu)建你自己的連接規(guī)格。例如哩掺,這個配置限制了三種德高望重的加密套件凿叠。它的缺陷是需要Android5.0版本以上以及一個類似先進網(wǎng)路服務(wù)器。
ConnectionSpec spec = new ConnectionSpec.Builder(ConnectionSpec.MODERN_TLS)
.tlsVersions(TlsVersion.TLS_1_2)
.cipherSuites(
CipherSuite.TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256,
CipherSuite.TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256,
CipherSuite.TLS_DHE_RSA_WITH_AES_128_GCM_SHA256)
.build();
OkHttpClient client = new OkHttpClient.Builder()
.connectionSpecs(Collections.singletonList(spec))
.build();
認證綁定
默認嚼吞,OkHttp信任主機平臺的證書頒發(fā)機構(gòu)盒件。這個策略最大化了連通性,但是它也受限制于像2011 DigiNotar attack的證書頒發(fā)機構(gòu)攻擊舱禽。它也假定你的HTTPS服務(wù)器證書也是由證書頒發(fā)機構(gòu)簽署炒刁。
使用CertificatePinner來限制哪些證書和證書頒發(fā)機構(gòu)可以被信任。證書鎖定提升安全性誊稚,但是限制你的服務(wù)器團隊更新他們的TLS證書的能力翔始。如果沒有你的服務(wù)器的TLS管理員的祝福罗心,不要使用證書鎖定!
public CertificatePinning() {
client = new OkHttpClient.Builder()
.certificatePinner(new CertificatePinner.Builder()
.add("publicobject.com", "sha256/afwiKY3RxoMmLkuRW1l7QsPZTJPwDS2pdDROQjXw8ig=")
.build())
.build();
}
public void run() throws Exception {
Request request = new Request.Builder()
.url("https://publicobject.com/robots.txt")
.build();
Response response = client.newCall(request).execute();
if (!response.isSuccessful()) throw new IOException("Unexpected code " + response);
for (Certificate certificate : response.handshake().peerCertificates()) {
System.out.println(CertificatePinner.pin(certificate));
}
}
自定義可信任證書機構(gòu)
全部的代碼樣例展示了如果使用你自己的證書頒發(fā)機構(gòu)替換主機的城瞎。跟上面一樣渤闷,如果沒有你的服務(wù)器的TLS管理員的祝福,不要使用證書鎖定脖镀!
private final OkHttpClient client;
public CustomTrust() {
SSLContext sslContext = sslContextForTrustedCertificates(trustedCertificatesInputStream());
client = new OkHttpClient.Builder()
.sslSocketFactory(sslContext.getSocketFactory())
.build();
}
public void run() throws Exception {
Request request = new Request.Builder()
.url("https://publicobject.com/helloworld.txt")
.build();
Response response = client.newCall(request).execute();
System.out.println(response.body().string());
}
private InputStream trustedCertificatesInputStream() {
... // Full source omitted. See sample.
}
public SSLContext sslContextForTrustedCertificates(InputStream in) {
... // Full source omitted. See sample.
}
原文鏈接:
https://github.com/square/okhttp/wiki/HTTPS
OkHttp官方文檔系列文章: