1. ホーム
  2. android

[解決済み] okHttpですべての証明書を信頼する

2022-06-12 21:30:17

質問

テスト目的のために、私はプロキシが設定されている間すべてを信頼するソケットファクトリを私のokHttpクライアントに追加しようとしています。これは何度も繰り返されてきましたが、信頼するソケット ファクトリーの私の実装は、何かが欠けているようです。

class TrustEveryoneManager implements X509TrustManager {
    @Override
    public void checkClientTrusted(java.security.cert.X509Certificate[] chain, String authType) throws CertificateException { }

    @Override
    public void checkServerTrusted(java.security.cert.X509Certificate[] chain, String authType) throws CertificateException { }

    @Override
    public java.security.cert.X509Certificate[] getAcceptedIssuers() {
        return null;
    }
}
OkHttpClient client = new OkHttpClient();

final InetAddress ipAddress = InetAddress.getByName("XX.XXX.XXX.XXX"); // some IP
client.setProxy(new Proxy(Proxy.Type.HTTP, new InetSocketAddress(ipAddress, 8888)));

SSLContext sslContext = SSLContext.getInstance("TLS");
TrustManager[] trustManagers = new TrustManager[]{new TrustEveryoneManager()};
sslContext.init(null, trustManagers, null);
client.setSslSocketFactory(sslContext.getSocketFactory);

私のアプリからリクエストが送信されることはなく、例外も記録されないので、okHttp の中で静かに失敗しているようです。さらに調査したところ、okHttp の Connection.upgradeToTls() の中で飲み込まれている例外があるようです。私が受けている例外は javax.net.ssl.SSLException: SSL handshake terminated: ssl=0x74b522b0: SSL_ERROR_ZERO_RETURN occurred. You should never see this.

次のコードでは SSLContext を生成し、例外を発生させない SSLSocketFactory を作成するのに魅力的に動作します。

protected SSLContext getTrustingSslContext() throws NoSuchAlgorithmException, KeyStoreException, KeyManagementException {
    final SSLContextBuilder trustingSSLContextBuilder = SSLContexts.custom()
            .loadTrustMaterial(null, new TrustStrategy() {
                @Override
                public boolean isTrusted(X509Certificate[] chain, String authType) throws CertificateException {
                    return true; // Accepts any ssl cert whether valid or not.
                }
            });
    return trustingSSLContextBuilder.build();
}

問題は、私のアプリからすべてのApache HttpClientの依存性を完全に削除しようとしていることです。Apache HttpClient を使用した基礎となるコードで SSLContext を生成する Apache HttpClient の基本的なコードは十分に単純に見えますが、私は明らかに何かを見逃しているようです。 SSLContext を設定することができないので、明らかに何かを見逃しています。

Apache HttpClient を使用せずに、私が望むことを行う SSLContext の実装を作成できる方はいらっしゃいますか?

どのように解決するのですか?

誰かがここに落ちる念のために、私のために働いた(唯一の)解決策は、作成されています。 OkHttpClient を作成することです。 ここで .

以下はそのコードです。

private static OkHttpClient getUnsafeOkHttpClient() {
  try {
    // Create a trust manager that does not validate certificate chains
    final TrustManager[] trustAllCerts = new TrustManager[] {
        new X509TrustManager() {
          @Override
          public void checkClientTrusted(java.security.cert.X509Certificate[] chain, String authType) throws CertificateException {
          }

          @Override
          public void checkServerTrusted(java.security.cert.X509Certificate[] chain, String authType) throws CertificateException {
          }

          @Override
          public java.security.cert.X509Certificate[] getAcceptedIssuers() {
            return new java.security.cert.X509Certificate[]{};
          }
        }
    };

    // Install the all-trusting trust manager
    final SSLContext sslContext = SSLContext.getInstance("SSL");
    sslContext.init(null, trustAllCerts, new java.security.SecureRandom());
    // Create an ssl socket factory with our all-trusting manager
    final SSLSocketFactory sslSocketFactory = sslContext.getSocketFactory();

    OkHttpClient.Builder builder = new OkHttpClient.Builder();
    builder.sslSocketFactory(sslSocketFactory, (X509TrustManager)trustAllCerts[0]);
    builder.hostnameVerifier(new HostnameVerifier() {
      @Override
      public boolean verify(String hostname, SSLSession session) {
        return true;
      }
    });

    OkHttpClient okHttpClient = builder.build();
    return okHttpClient;
  } catch (Exception e) {
    throw new RuntimeException(e);
  }
}