Проблемы с сертификатом проверки имени хоста Play Framework WS
Я использую Play Framework 2.3.8, и у меня возникают проблемы с выполнением HTTPS-запросов к определенным хостам. В этом случае я не могу подключиться к хосту API Zendesk (xxxxx.zendesk.com) с помощью клиента WS.
Ошибка, которую я получаю изначально:
Невозможно вызвать действие, в итоге возникла ошибка: java.net.ConnectException: исключение HostnameVerifier.
Это странно, потому что сертификат выглядит как файл, если я просматриваю его в браузере или через ssl s_client. Запись CN соответствует домену.
Если я отключаю проверку имени хоста, я получаю сообщение об ошибке от Cloudflare с сообщением "Запрещено". Это в HTML, а не в JSON, что не то, что я ожидаю.
Затем я попытался отправить тот же запрос с почтальоном и curl. Запрос успешно выполнен, и я получил ответ обратно в формате JSON.
Затем я использовал Charles Web Debugging Proxy, чтобы перехватывать HTTPS-запросы от Play Framework и сравнивать его с запросами, отправленными Postman. Как ни странно, запросы выполнялись успешно, если Чарльз перехватывал запросы! Чарльз не пролил свет на вопрос сертификата.
Я видел, как другие люди жаловались на подобные проблемы с Cloudflare, и в их случае оказалось, что их клиент не поддерживает TLS 1.2. Я проверил и запустил версию 1.8 JVM, которая поддерживает TLS 1.2 по умолчанию, и даже попытался принудительно использовать TLS 1.2 с помощью переменной конфигурации на всякий случай, и это не помогло.
Я полагаю, что есть проблема с SSL в используемой версии Play Framework.
2 ответа
Наконец, я попытался использовать Wireshark в качестве последнего средства, чтобы попытаться определить различия между запросами, отправленными от других моих клиентов (curl/Postman) и от клиента Play Framework WS.
Я заметил, что работающие клиенты отправили доменное имя как часть рукопожатия. Затем он щелкнул, что это может быть проблемой SNI.
Конечно, Play Framework 2.3.x не поддерживает SNI.
Единственными двумя реальными вариантами было использование отдельного HTTP-клиента, такого как play-ws, или обновление моей версии Play Framework до 2.4.x.
Я выбрал последнее, и теперь оно работает.
Проблема проверки имени хоста была на самом деле красной сельдью и связана с отсутствием поддержки SNI. Я смог включить его без проблем.
Я надеюсь, что это помогает кому-то с той же проблемой!
Вы можете вручную переопределить доверенные URL-адреса в верификаторе (только если вы доверяете целевому URL-адресу). Переопределить HostnameVerifier в одном классе и добавить доверенный домен. создайте класс, например, MyHostnameVerifier, как показано ниже.
public class MyHostnameVerifier implements javax.net.ssl.HostnameVerifier {
@Override
public boolean verify(String hostname, javax.net.ssl.SSLSession sslSession) {
return hostname.contains("www.my-target-url.com");
}}
Надеюсь, это поможет.