Доверяя все сертификаты с okHttp



для целей тестирования я пытаюсь добавить фабрику сокетов к моему клиенту 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 кажется достаточно простым, но я, очевидно, отсутствует что-то как я не могу настроить мой SSLContext чтобы соответствовать этому.



сможет ли кто-нибудь создать реализацию SSLContext, которая делает то, что я хотел бы без использования Apache HttpClient?

650   5  

5 ответов:

на всякий случай, если кто-то упадет здесь, (единственное) решение, которое сработало для меня, создает 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);
  }
}

следующий метод является устаревшим

sslSocketFactory(SSLSocketFactory sslSocketFactory)

подумайте об обновлении его до

sslSocketFactory(SSLSocketFactory sslSocketFactory, X509TrustManager trustManager)

обновить okhttp3. 0 ,функция getAcceptedIssuers() должна возвращать пустой массив вместо null

SSLSocketFactory не предоставляет свой X509TrustManager, который является полем, которое OkHttp должен построить чистую цепочку сертификатов. Вместо этого этот метод должен использовать отражение для извлечения диспетчера доверия. Приложения должны предпочитать вызывать sslSocketFactory (SSLSocketFactory, X509TrustManager), что позволяет избежать такого отражения.

OkHttpClient.Builder builder = new OkHttpClient.Builder();

builder.sslSocketFactory(sslContext.getSocketFactory(),
                    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[]{};
                        }
                    });

вы никогда не должны искать, чтобы переопределить проверку сертификата в коде! Если вам нужно выполнить тестирование, используйте внутренний/тестовый CA и установите корневой сертификат CA на устройстве или эмуляторе. Вы можете использовать BurpSuite или Charles Proxy, если вы не знаете, как настроить CA.

Comments

    Ничего не найдено.