OkHttp之HTTPS

OkHttp盡力去平衡兩個相互競爭的關注點:

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

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

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

  • MODERN_TLS:一個連接先進HTTPS服務器的安全配置。
  • COMPATIBLE_TLS:一個連接安全但是非current-HTTPS服務器的安全配置。
  • CLEARTEXT:一個用于http://的URL的不安全配置。

默認,OkHttp會嘗試MODERN_TLS連接,如果先進配置失敗,則會回退到COMPATIBLE_TLS連接。

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

你可以使用一個自定義TLS版本和加密套件集構建你自己的連接規(guī)格。例如,這個配置限制了三種德高望重的加密套件。它的缺陷是需要Android5.0版本以上以及一個類似先進網(wǎng)路服務器。

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ā)機構。這個策略最大化了連通性,但是它也受限制于像2011 DigiNotar attack的證書頒發(fā)機構攻擊。它也假定你的HTTPS服務器證書也是由證書頒發(fā)機構簽署。

使用CertificatePinner來限制哪些證書和證書頒發(fā)機構可以被信任。證書鎖定提升安全性,但是限制你的服務器團隊更新他們的TLS證書的能力。如果沒有你的服務器的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));
    }
  }

自定義可信任證書機構

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

最后編輯于
?著作權歸作者所有,轉載或內容合作請聯(lián)系作者
【社區(qū)內容提示】社區(qū)部分內容疑似由AI輔助生成,瀏覽時請結合常識與多方信息審慎甄別。
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發(fā)布,文章內容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務。

相關閱讀更多精彩內容

友情鏈接更多精彩內容