Как установить версию TLS на apache HttpClient

Как изменить поддерживаемые версии TLS на моем HttpClient?

Я делаю:

SSLContext sslContext = SSLContext.getInstance("TLSv1.1"); sslContext.init( keymanagers.toArray(new KeyManager[keymanagers.size()]), null, null); SSLSocketFactory socketFactory = new SSLSocketFactory(sslContext, new String[]{"TLSv1.1"}, null, null); Scheme scheme = new Scheme("https", 443, socketFactory); SchemeRegistry schemeRegistry = new SchemeRegistry(); schemeRegistry.register(scheme); BasicClientConnectionManager cm = new BasicClientConnectionManager(schemeRegistry); httpClient = new DefaultHttpClient(cm); 

Но когда я проверяю созданный сокет, он все еще говорит, что поддерживаемые протоколы – TLSv1.0, TLSv1.1 и TLSv1.2.

На самом деле я просто хочу, чтобы он прекратил использовать TLSv1.2 для этого конкретного HttpClient.

Решение:

 SSLContext sslContext = SSLContexts.custom() .useTLS() .build(); SSLConnectionSocketFactory f = new SSLConnectionSocketFactory( sslContext, new String[]{"TLSv1", "TLSv1.1"}, null, BROWSER_COMPATIBLE_HOSTNAME_VERIFIER); httpClient = HttpClients.custom() .setSSLSocketFactory(f) .build(); 

Для этого требуется org.apache.httpcomponents.httpclient 4.3.x.

Вот как я работал над httpClient 4.5 (по запросу оливкового дерева):

 CredentialsProvider credsProvider = new BasicCredentialsProvider(); credsProvider.setCredentials( new AuthScope(AuthScope.ANY_HOST, 443), new UsernamePasswordCredentials(this.user, this.password)); SSLContext sslContext = SSLContexts.createDefault(); SSLConnectionSocketFactory sslsf = new SSLConnectionSocketFactory(sslContext, new String[]{"TLSv1", "TLSv1.1"}, null, new NoopHostnameVerifier()); CloseableHttpClient httpclient = HttpClients.custom() .setDefaultCredentialsProvider(credsProvider) .setSSLSocketFactory(sslsf) .build(); return httpclient; 

HttpClient-4.5, используйте TLSv1.2, вы должны сделать следующее:

  //Set the https use TLSv1.2 private static Registry getRegistry() throws KeyManagementException, NoSuchAlgorithmException { SSLContext sslContext = SSLContexts.custom().build(); SSLConnectionSocketFactory sslConnectionSocketFactory = new SSLConnectionSocketFactory(sslContext, new String[]{"TLSv1.2"}, null, SSLConnectionSocketFactory.getDefaultHostnameVerifier()); return RegistryBuilder.create() .register("http", PlainConnectionSocketFactory.getSocketFactory()) .register("https", sslConnectionSocketFactory) .build(); } public static void main(String... args) { try { //Set the https use TLSv1.2 PoolingHttpClientConnectionManager clientConnectionManager = new PoolingHttpClientConnectionManager(getRegistry()); clientConnectionManager.setMaxTotal(100); clientConnectionManager.setDefaultMaxPerRoute(20); HttpClient client = HttpClients.custom().setConnectionManager(clientConnectionManager).build(); //Then you can do : client.execute(HttpGet or HttpPost); } catch (KeyManagementException | NoSuchAlgorithmException e) { e.printStackTrace(); } } 

Для HttpClient-4.1 с использованием TLSv1.2 код будет выглядеть примерно так:

  SSLContext sslContext = SSLContext.getInstance("TLSv1.2"); sslContext.init(null, null, new SecureRandom()); SSLSocketFactory sf = new SSLSocketFactory(sslContext); Scheme httpsScheme = new Scheme("https", 443, sf); SchemeRegistry schemeRegistry = new SchemeRegistry(); schemeRegistry.register(httpsScheme); ClientConnectionManager cm = new SingleClientConnManager(schemeRegistry); HttpClient client = new DefaultHttpClient(cm); // Use client to make the connection and get the results. 

Если вы используете httpclient 4.2, вам нужно написать небольшой бит дополнительного кода. Я хотел иметь возможность настраивать как «протоколы с поддержкой TLS» (например, TLSv1.1 , так и ни TLSv1 ни TLSv1.2 ), а также TLSv1.2 шифров .

 public class CustomizedSSLSocketFactory extends SSLSocketFactory { private String[] _tlsProtocols; private String[] _tlsCipherSuites; public CustomizedSSLSocketFactory(SSLContext sslContext, X509HostnameVerifier hostnameVerifier, String[] tlsProtocols, String[] cipherSuites) { super(sslContext, hostnameVerifier); if(null != tlsProtocols) _tlsProtocols = tlsProtocols; if(null != cipherSuites) _tlsCipherSuites = cipherSuites; } @Override protected void prepareSocket(SSLSocket socket) { // Enforce client-specified protocols or cipher suites if(null != _tlsProtocols) socket.setEnabledProtocols(_tlsProtocols); if(null != _tlsCipherSuites) socket.setEnabledCipherSuites(_tlsCipherSuites); } } 

Затем:

  SSLContext sslContext = SSLContext.getInstance("TLS"); sslContext.init(null, getTrustManagers(), new SecureRandom()); // NOTE: not javax.net.SSLSocketFactory SSLSocketFactory sf = new CustomizedSSLSocketFactory(sslContext, null, [TLS protocols], [TLS cipher suites]); Scheme httpsScheme = new Scheme("https", 443, sf); SchemeRegistry schemeRegistry = new SchemeRegistry(); schemeRegistry.register(httpsScheme); ConnectionManager cm = new BasicClientConnectionManager(schemeRegistry); HttpClient client = new DefaultHttpClient(cmgr); ... 

Возможно, вы сможете сделать это со слегка меньшим количеством кода, но я в основном копирую / вставляю из пользовательского компонента, где имеет смысл создавать объекты таким образом, как показано выше.

Если в вашем коде есть ссылка classа javax.net.ssl.SSLSocket , вы можете установить разрешенные TLS-протоколы вызовом SSLSocket.setEnabledProtocols () :

 import javax.net.ssl.*; import java.net.*; ... Socket socket = SSLSocketFactory.getDefault().createSocket(); ... if (socket instanceof SSLSocket) { // "TLSv1.0" gives IllegalArgumentException in Java 8 String[] protos = {"TLSv1.2", "TLSv1.1"} ((SSLSocket)socket).setEnabledProtocols(protos); } 

Использование HttpClientBuilder в HttpClient 4.5.x с помощью настраиваемого HttpClientConnectionManager с настройками HttpClientBuilder по умолчанию:

 SSLConnectionSocketFactory sslConnectionSocketFactory = new SSLConnectionSocketFactory(SSLContexts.createDefault(), new String[] { "TLSv1.2" }, null, SSLConnectionSocketFactory.getDefaultHostnameVerifier()); PoolingHttpClientConnectionManager poolingHttpClientConnectionManager = new PoolingHttpClientConnectionManager( RegistryBuilder. create() .register("http", PlainConnectionSocketFactory.getSocketFactory()) .register("https", sslConnectionSocketFactory) .build()); // Customize the connection pool CloseableHttpClient httpClient = HttpClientBuilder.create() .setConnectionManager(poolingHttpClientConnectionManager) .build() 

Без пользовательского HttpClientConnectionManager :

 SSLConnectionSocketFactory sslConnectionSocketFactory = new SSLConnectionSocketFactory(SSLContexts.createDefault(), new String[] { "TLSv1.2" }, null, SSLConnectionSocketFactory.getDefaultHostnameVerifier()); CloseableHttpClient httpClient = HttpClientBuilder.create() .setSSLSocketFactory(sslConnectionSocketFactory) .build() 

Вы можете просто указать следующее свойство -Dhttps.protocols = TLSv1.1, TLSv1.2 на вашем сервере, который настраивает JVM, чтобы указать, какая версия протокола TLS должна использоваться во время всех https-соединений от клиента.

Использование -Dhttps.protocols = TLSv1.2 Аргумент JVM не работал для меня. Что работает, следующий код

 RequestConfig.Builder requestBuilder = RequestConfig.custom(); //other configuration, for example requestBuilder = requestBuilder.setConnectTimeout(1000); SSLContext sslContext = SSLContextBuilder.create().useProtocol("TLSv1.2").build(); HttpClientBuilder builder = HttpClientBuilder.create(); builder.setDefaultRequestConfig(requestBuilder.build()); builder.setProxy(new HttpHost("your.proxy.com", 3333)); //if you have proxy builder.setSSLContext(sslContext); HttpClient client = builder.build(); 

Используйте следующий аргумент JVM для проверки

 -Djavax.net.debug=all 
  • Https Connection Android
  • Доверяйте всем сертификатам, используя HttpClient over HTTPS
  • Использование makecert для разработки SSL
  • почему Java не отправляет сертификат клиента во время подтверждения SSL?
  • Как установить: OpenSSL + WAMP
  • Thunderbird: Ошибка: imap.server.com: сервер не поддерживает RFC 5746, см. CVE-2009-3555
  • Преобразовать .pem в .crt и .key
  • SSLHandshakeException: нет альтернативных имен объектов
  • GMail и SSL Encryption - сколько зашифровано
  • curl: (60) SSL-сертификат: не удалось получить сертификат локального эмитента
  • Подключение к WebSphere MQ в Java с помощью SSL / Keystore
  • Давайте будем гением компьютера.