OkHttp之HTTPS

OkHttp尽力去平衡两个相互竞争的关注点:

  • Connectivity:尽可能地连接更多地主机。这个包括运行boringssl最新版本的先进主机和运行OpenSSL老版本的稍微过时的主机。
  • Security:连接的安全性。这个包括使用证书验证远程网络服务器和使用强密码的数据交换隐私。

当涉及到一个到HTTPS服务器的连接时,OkHttp需要知道提供哪个TLS版本和安全套件。一个客户端想要最大化连通性会包含废弃的TLS版本和weak-by-design密码套件。一个严谨的客户端想要最大化连通性会限制只能用最新TLS版本和最强的密码套件。

特定的安全vs连通性决策通过ConnectionSpec实现。OkHttp包含三个内置的连接规格:

  • MODERN_TLS:一个连接先进HTTPS服务器的安全配置。
  • COMPATIBLE_TLS:一个连接安全但是非current-HTTPS服务器的安全配置。
  • CLEARTEXT:一个用于http://的URL的不安全配置。

默认,OkHttp会尝试MODERN_TLS连接,如果先进配置失败,则会回退到COMPATIBLE_TLS连接。

TLS版本和加密套件的规格可能随着每个版本改变。例如,在OkHttp2.2,我们放弃支持SSL3.0作为POODLE攻击的响应。在OkHttp2.3放弃支持RC4.与你的桌面网络浏览器一样,保持OkHttp最新是保持安全的最好方式。

你可以使用一个自定义TLS版本和加密套件集构建你自己的连接规格。例如,这个配置限制了三种德高望重的加密套件。它的缺陷是需要Android5.0版本以上以及一个类似先进网路服务器。

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信任主机平台的证书颁发机构。这个策略最大化了连通性,但是它也受限制于像2011 DigiNotar attack的证书颁发机构攻击。它也假定你的HTTPS服务器证书也是由证书颁发机构签署。

使用CertificatePinner来限制哪些证书和证书颁发机构可以被信任。证书锁定提升安全性,但是限制你的服务器团队更新他们的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));
    }
  }

自定义可信任证书机构

全部的代码样例展示了如果使用你自己的证书颁发机构替换主机的。跟上面一样,如果没有你的服务器的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官方文档系列文章:

  • OkHttp之简介
  • OkHttp之Call
  • OkHttp之连接
  • OkHttp之示例
  • OkHttp之拦截器
  • OkHttp之HTTPS

你可能感兴趣的:(OkHttp之HTTPS)