OkHttp之HTTPS

OkHttp盡力去平衡兩個(gè)相互競(jìng)爭(zhēng)的關(guān)注點(diǎn):

  • Connectivity:盡可能地連接更多地主機(jī)。這個(gè)包括運(yùn)行boringssl最新版本的先進(jìn)主機(jī)和運(yùn)行OpenSSL老版本的稍微過(guò)時(shí)的主機(jī)。
  • Security:連接的安全性。這個(gè)包括使用證書驗(yàn)證遠(yuǎn)程網(wǎng)絡(luò)服務(wù)器和使用強(qiáng)密碼的數(shù)據(jù)交換隱私。

當(dāng)涉及到一個(gè)到HTTPS服務(wù)器的連接時(shí),OkHttp需要知道提供哪個(gè)TLS版本和安全套件。一個(gè)客戶端想要最大化連通性會(huì)包含廢棄的TLS版本和weak-by-design密碼套件。一個(gè)嚴(yán)謹(jǐn)?shù)目蛻舳讼胍畲蠡B通性會(huì)限制只能用最新TLS版本和最強(qiáng)的密碼套件。

特定的安全vs連通性決策通過(guò)ConnectionSpec實(shí)現(xiàn)。OkHttp包含三個(gè)內(nèi)置的連接規(guī)格:

  • MODERN_TLS:一個(gè)連接先進(jìn)HTTPS服務(wù)器的安全配置。
  • COMPATIBLE_TLS:一個(gè)連接安全但是非current-HTTPS服務(wù)器的安全配置。
  • CLEARTEXT:一個(gè)用于http://的URL的不安全配置。

默認(rèn),OkHttp會(huì)嘗試MODERN_TLS連接,如果先進(jìn)配置失敗,則會(huì)回退到COMPATIBLE_TLS連接。

TLS版本和加密套件的規(guī)格可能隨著每個(gè)版本改變。例如,在OkHttp2.2,我們放棄支持SSL3.0作為POODLE攻擊的響應(yīng)。在OkHttp2.3放棄支持RC4.與你的桌面網(wǎng)絡(luò)瀏覽器一樣,保持OkHttp最新是保持安全的最好方式。

你可以使用一個(gè)自定義TLS版本和加密套件集構(gòu)建你自己的連接規(guī)格。例如,這個(gè)配置限制了三種德高望重的加密套件。它的缺陷是需要Android5.0版本以上以及一個(gè)類似先進(jìn)網(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();

認(rèn)證綁定

默認(rèn),OkHttp信任主機(jī)平臺(tái)的證書頒發(fā)機(jī)構(gòu)。這個(gè)策略最大化了連通性,但是它也受限制于像2011 DigiNotar attack的證書頒發(fā)機(jī)構(gòu)攻擊。它也假定你的HTTPS服務(wù)器證書也是由證書頒發(fā)機(jī)構(gòu)簽署。

使用CertificatePinner來(lái)限制哪些證書和證書頒發(fā)機(jī)構(gòu)可以被信任。證書鎖定提升安全性,但是限制你的服務(wù)器團(tuán)隊(duì)更新他們的TLS證書的能力。如果沒(méi)有你的服務(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));
    }
  }

自定義可信任證書機(jī)構(gòu)

全部的代碼樣例展示了如果使用你自己的證書頒發(fā)機(jī)構(gòu)替換主機(jī)的。跟上面一樣,如果沒(méi)有你的服務(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官方文檔系列文章:

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

推薦閱讀更多精彩內(nèi)容