Как установить версию 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.
- Каков правильный способ безопасного отключения сокета SSL asio?
- Java-соединение и HTTPS-соединение без скачивания сертификата
- Решение javax.net.ssl.SSLHandshakeException: sun.security.validator.ValidatorException: PKIX path building failed Ошибка?
- Знак предупреждения Thunderbird продолжает появляться
- Heroku NodeJS http to https ssl принудительное redirect
На самом деле я просто хочу, чтобы он прекратил использовать TLSv1.2 для этого конкретного HttpClient.
- Сколько информации может видеть мой интернет-провайдер?
- Java: функция переопределения для отключения проверки сертификата SSL
- Delphi: idHttp + SSL
- Почему OS X не доверяет SSL-сертификату GitHub?
- Тип Keystore: какой из них использовать?
- Javax.net.ssl.SSLHandshakeException: javax.net.ssl.SSLProtocolException: SSL-квитирование отменено: ошибка в библиотеке SSL, обычно ошибка протокола
- Принять самоподписанный сертификат ssl сервера в Java-клиенте
- Как всегда разрешать небезопасное соединение для определенного URL-адреса в хроме?
Решение:
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