7

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

Я был используя решения этой проблемы из кучки сообщений на SO. Пока никто из них не работал.

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

Apache Docs:

Связанные StackOverflow Questions - Вот некоторые ссылки решений я попробовал:

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

Try # 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

Try # 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(); 

РЕЗУЛЬТАТ: Не работает. Got Error while trying to execute request. javax.net.ssl.SSLHandshakeException: Remote host closed connection during handshake

Try # 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

Try # 4

я нашел что-то полезное из this answer:

As of version 4.5 HttpClient disables SSLv3 protocol version by default

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

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

Решение

Это довольно неудобно, но мне просто нужно изменить порт при подключении к SSL:

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

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

ответ

1

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

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

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

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

Или вы можете следовать this tutorial.

Удачи.

+0

Да, вы правы. Я просто попытался перейти на фактический сайт, и я думаю, что он не работает, они, возможно, работали все это время – Kayvar

2
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(); 
    } 
+3

Добавьте несколько комментариев и описание. – Masoud

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(); 
} 
2

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

PKIX Path building failed

.

Я нашел решение в 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(); 
}