Игнорировать самозаверяющие сертификаты в Apache HTTPClient 4.5

Я пытаюсь принять все сертификаты и/или принять самозаверяющие сертификаты, используя Apache HTTPClient версии 4.5 (ссылка на учебник здесь)

Я рассматривал решение этой проблемы из множества постов на SO. Пока что ни один из них не работал.

Я получаю эту ошибку: Error while trying to execute request. javax.net.ssl.SSLHandshakeException: Remote host closed connection during handshake

Документы Apache:

Вопросы по Qaru - Вот несколько ссылок на решения, которые я пробовал:

Обратите внимание, что во всех этих примерах я также передаю хранилище файлов cookie и поставщик учетных данных прокси, который я определил ранее. Они работают, я просто пытаюсь добавить поддержку SSL.

Попробуйте # 1

Создайте свой собственный контекст ssl с SSLContextBuilder и доверьтесь всем самоподписанным стратегиям с TrustSelfSignedStrategy.

SSLContextBuilder sshbuilder = new SSLContextBuilder();
sshbuilder.loadTrustMaterial(null, new TrustSelfSignedStrategy());
SSLConnectionSocketFactory sslsf = new SSLConnectionSocketFactory(sshbuilder.build());

CloseableHttpClient httpclient = HttpClients.custom()
    .setDefaultCredentialsProvider(credsProvider)
    .setDefaultCookieStore(cookieStore)
    .setSSLSocketFactory(sslsf)
    .build();

РЕЗУЛЬТАТ: не сработало. Получил Error while trying to execute request. javax.net.ssl.SSLHandshakeException: Remote host closed connection during handshake

Попробуйте №2

То же, что и выше, но добавьте PoolingHttpClientConnectionManager

SSLContextBuilder builder = new SSLContextBuilder();
builder.loadTrustMaterial(null, new TrustSelfSignedStrategy());
SSLConnectionSocketFactory sslsf = new SSLConnectionSocketFactory(builder.build(),SSLConnectionSocketFactory.ALLOW_ALL_HOSTNAME_VERIFIER);
Registry<ConnectionSocketFactory> registry = RegistryBuilder.<ConnectionSocketFactory>create()
        .register("http", new PlainConnectionSocketFactory())
        .register("https", sslsf)
        .build();
PoolingHttpClientConnectionManager cm = new PoolingHttpClientConnectionManager(registry);
cm.setMaxTotal(2000);//max connection

CloseableHttpClient httpclient = HttpClients.custom()
    .setDefaultCredentialsProvider(credsProvider)
    .setDefaultCookieStore(cookieStore)
    .setSSLSocketFactory(sslsf)
    .setConnectionManager(cm)
    .build();

РЕЗУЛЬТАТ: не сработало. Получил Error while trying to execute request. javax.net.ssl.SSLHandshakeException: Remote host closed connection during handshake

Попробуйте №3

Просто примите ВСЕ сертификаты, переопределив TrustStrategy (это не рекомендуется)

SSLContextBuilder builder = new SSLContextBuilder();
builder.loadTrustMaterial(null, new TrustStrategy() {
    @Override
    public boolean isTrusted(X509Certificate[] chain, String authType) throws CertificateException {
        return true;
    }
});
SSLConnectionSocketFactory sslsf = new SSLConnectionSocketFactory(builder.build(),
    SSLConnectionSocketFactory.ALLOW_ALL_HOSTNAME_VERIFIER);

CloseableHttpClient httpclient = HttpClients.custom()
    .setDefaultCredentialsProvider(credsProvider)
    .setDefaultCookieStore(cookieStore)
    .setSSLSocketFactory(sslsf)
    .build();

РЕЗУЛЬТАТ: не сработало. Получил Error while trying to execute request. javax.net.ssl.SSLHandshakeException: Remote host closed connection during handshake

Попробуйте # 4

Я нашел что-то полезное из этого ответа:

Начиная с версии 4.5, HttpClient отключает версию протокола SSLv3 по умолчанию

Вот решение, которое он дал:

SSLContext sslcontext = SSLContexts.createSystemDefault();
SSLConnectionSocketFactory sslConnectionSocketFactory = new SSLConnectionSocketFactory(
        sslcontext, new String[] { "TLSv1", "SSLv3" }, null,
        SSLConnectionSocketFactory.getDefaultHostnameVerifier());

Registry<ConnectionSocketFactory> socketFactoryRegistry = RegistryBuilder.<ConnectionSocketFactory>create()
        .register("http", PlainConnectionSocketFactory.INSTANCE)
        .register("https", sslConnectionSocketFactory)
        .build();
PoolingHttpClientConnectionManager cm = new PoolingHttpClientConnectionManager(socketFactoryRegistry);

httpclient = HttpClients.custom()
    .setDefaultCredentialsProvider(credsProvider)
    .setDefaultCookieStore(cookieStore)
    .setSSLSocketFactory(sslConnectionSocketFactory)
    .setConnectionManager(cm)
    .build();

РЕЗУЛЬТАТ: не сработало. Получил Error while trying to execute request. javax.net.ssl.SSLHandshakeException: Remote host closed connection during handshake

Ответ 1

Один из вышеперечисленных подходов должен работать в случае самозаверяющих сертификатов, но странно то, что вы получаете одно и то же исключение во всех подходах.

Я чувствую, что во время установления сеанса SSL или протокола квитирования не принимается ни клиентом, ни сервером.

Лучшее решение здесь - отладка приложения.

В случае tomcat добавьте -Djavax.net.debug = all в файлы setenv.sh или setenv.bat, а затем перезапустите сервер.

Или вы можете следовать этому руководству.

OP просто необходимо изменить порт при подключении к SSL:

//For HTTPS
HttpHost httpstarget = new HttpHost("mysite.com", 443, "https");

//For HTTP
HttpHost httptarget = new HttpHost("mysite.com", 80, "http");

Ответ 2

Я использую Apache HttpClient 4.5.3 и ни одно из вышеперечисленных решений не помогло. Я всегда получаю ошибку

Ошибка построения пути PKIX

.

Я нашел решение в http://www.baeldung.com/httpclient-ssl

Вот мой код:

try {
    SSLContext sslContext = new SSLContextBuilder()
            .loadTrustMaterial(null, (certificate, authType) -> true).build();
    httpClient = HttpClients.custom().setSSLContext(sslContext)
            .setSSLHostnameVerifier(new NoopHostnameVerifier())
            .build();
} catch (NoSuchAlgorithmException | KeyManagementException | KeyStoreException e) {
    e.printStackTrace();
}

Ответ 3

Очень часто вам необходимо не только поддерживать самоподписанные сертификаты, но также вызывать многопоточные запросы, поэтому используйте диспетчер подключений пула. Вот как я это делаю:

private CloseableHttpClient newClient() throws KeyManagementException, NoSuchAlgorithmException, KeyStoreException {
    SSLContext context = SSLContexts.custom()
            .loadTrustMaterial(TrustSelfSignedStrategy.INSTANCE)
            .build();

    Registry<ConnectionSocketFactory> registry = RegistryBuilder.<ConnectionSocketFactory> create()
            .register("http", PlainConnectionSocketFactory.INSTANCE)
            .register("https", new SSLConnectionSocketFactory(context, NoopHostnameVerifier.INSTANCE))
            .build();

    PoolingHttpClientConnectionManager connectionManager = new PoolingHttpClientConnectionManager(registry);

    return HttpClients.custom()
            .setConnectionManager(connectionManager)
            .build();
}

Ответ 4

public static HttpClient newClient() {
        SSLContext sslcontext = null;
        try {
            sslcontext = SSLContexts.custom().loadTrustMaterial(null, new TrustSelfSignedStrategy()).build();
        } catch (NoSuchAlgorithmException | KeyManagementException | KeyStoreException e) {
            e.printStackTrace();
        }

        SSLConnectionSocketFactory sslConnectionSocketFactory = new SSLConnectionSocketFactory(sslcontext,
                (s, sslSession) -> true);

        return HttpClients.custom().setSSLSocketFactory(sslConnectionSocketFactory)
                .build();
    }