1. введение
Apache HttpClient-это низкоуровневая, легкая клиентская HTTP-библиотека для взаимодействия с HTTP-серверами. В этом руководстве мы узнаем, как настроить поддерживаемые версии безопасности транспортного уровня (TLS) при использовании HttpClient . Мы начнем с обзора того, как работает согласование версий TLS между клиентом и сервером. После этого мы рассмотрим три различных способа настройки поддерживаемых версий TLS при использовании HttpClient .
2. Согласование версии TLS
TLS-это интернет-протокол, который обеспечивает безопасную и надежную связь между двумя сторонами. Он инкапсулирует протоколы прикладного уровня, такие как HTTP. Протокол TLS несколько раз пересматривался с момента его первой публикации в 1999 году. Поэтому важно, чтобы клиент и сервер сначала договорились о том, какую версию TLS они будут использовать при установлении нового соединения. Версия TLS согласовывается после обмена приветственными сообщениями между клиентом и сервером:
- Клиент отправляет список поддерживаемых версий TLS.
- Сервер выбирает один из них и включает выбранную версию в ответ.
- Клиент и сервер продолжают настройку соединения, используя выбранную версию.
Важно правильно настроить поддерживаемые версии TLS веб-клиента из-за риска атаки понижения рейтинга . Обратите внимание, что для использования последней версии TLS (TLS 1.3) мы должны использовать Java 11 или более позднюю версию.
3. Статическая установка версии TLS
3.1. SSLConnectionSocketFactory
Давайте использовать HttpClientBuilder , предоставленный методом HttpClients#custom builder, чтобы настроить нашу конфигурацию HttpClient . Этот шаблон компоновщика позволяет нам передать наш собственный SSLConnectionSocketFactory , который будет создан с требуемым набором поддерживаемых версий TLS:
SSLConnectionSocketFactory sslsf = new SSLConnectionSocketFactory( SSLContexts.createDefault(), new String[] { "TLSv1.2", "TLSv1.3" }, null, SSLConnectionSocketFactory.getDefaultHostnameVerifier()); CloseableHttpClient httpClient = HttpClients.custom().setSSLSocketFactory(sslsf).build();
Возвращенный объект Httpclient теперь может выполнять HTTP-запросы. Установив поддерживаемые протоколы явно в конструкторе SSLConnectionSocketFactory , клиент будет поддерживать связь только через TLS 1.2 или TLS 1.3. Обратите внимание, что в версиях Apache HttpClient до версии 4.3 класс назывался SSLSocketFactory .
3.2. Аргумент среды выполнения Java
Кроме того, мы можем настроить поддерживаемые версии TLS с помощью системного свойства Java https.protocols . Этот метод предотвращает необходимость жесткого ввода значений в код приложения. Вместо этого мы настроим HttpClient для использования системных свойств при настройке соединений. API HttpClient предоставляет два способа сделать это. Первый – через Http-клиенты#создать систему :
CloseableHttpClient httpClient = HttpClients.createSystem();
Если требуется дополнительная конфигурация клиента, вместо этого мы можем использовать метод компоновщика:
CloseableHttpClient httpClient = HttpClients.custom().useSystemProperties().build();
Оба метода говорят HttpClient для использования системных свойств при настройке соединения. Это позволяет нам устанавливать необходимые версии TLS с помощью аргумента командной строки во время выполнения приложения. Например:
$ java -Dhttps.protocols=TLSv1.1,TLSv1.2,TLSv1.3 -jar webClient.jar
4. Динамическая настройка версии TLS
Также можно установить версию TLS на основе сведений о соединении, таких как имя хоста и порт. Мы расширим SSLConnectionSocketFactory и переопределим метод prepare Socket . Клиент вызывает метод prepare Socket , прежде чем инициировать новое соединение. Это позволит нам решить, какие протоколы TLS использовать для каждого соединения. Также можно включить поддержку более старых версий TLS, но только в том случае, если удаленный хост имеет определенный поддомен:
SSLConnectionSocketFactory sslsf = new SSLConnectionSocketFactory(SSLContexts.createDefault()){ @Override protected void prepareSocket(SSLSocket socket) { String hostname = socket.getInetAddress().getHostName(); if (hostname.endsWith("internal.system.com")){ socket.setEnabledProtocols(new String[] { "TLSv1", "TLSv1.1", "TLSv1.2", "TLSv1.3" }); } else { socket.setEnabledProtocols(new String[] {"TLSv1.3"}); } } };
CloseableHttpClient httpClient = HttpClients.custom().setSSLSocketFactory(sslsf).build();
В приведенном выше примере метод prepareSocket сначала получает имя удаленного хоста, к которому будет подключаться SSLSocket . Имя хоста затем используется для определения с помощью протоколов TLS для включения. Теперь наш HTTP-клиент будет применять TLS 1.3 для каждого запроса, за исключением случаев, когда имя хоста назначения имеет форму * .internal.example.com. С возможностью вставки пользовательской логики перед созданием нового SSLSocket наше приложение теперь может настраивать детали связи TLS.
5. Заключение
В этой статье мы рассмотрели три различных способа настройки поддерживаемых версий TLS при использовании библиотеки Apache HttpClient. Мы видели, как версии TLS могут быть установлены для всех соединений или на основе каждого соединения. Примеры кода, используемые в этой статье, доступны на GitHub .