Любое из вышеуказанных решений будет работать для самозаверяющего сертификата. Третий вариант - в случае, когда сервер предоставляет действительный, неподписанный сертификат, но для хоста, который не совпадает ни с одним из имен в сертификате, который он предоставляет, тогда системное свойство "jdk.internal.httpclient.disableHostnameVerification" может быть установлено в "true", и это заставит сертификат быть принятым так же, как API HostnameVerifier использовался ранее. Обратите внимание, что в обычных развертываниях не ожидается использование какого-либо из этих механизмов, поскольку должна быть возможность автоматической проверки сертификата, предоставленного любым правильно настроенным сервером HTTPS.
а необходимо разрешить небезопасные соединения HTTPS, например, в некоторых веб-приложениях, которые должны работать с любым сайтом. я использовалодно такое решение со старым HttpsURLConnection API, который недавно был замененновый HttpClient API в JDK 11. Как разрешить небезопасные соединения HTTPS (самозаверяющий или устаревший сертификат) с этим новым API?
UPD: код, который я пробовал (в Kotlin, но отображается непосредственно на Java):
val trustAllCerts = arrayOf<TrustManager>(object: X509TrustManager {
override fun getAcceptedIssuers(): Array<X509Certificate>? = null
override fun checkClientTrusted(certs: Array<X509Certificate>, authType: String) {}
override fun checkServerTrusted(certs: Array<X509Certificate>, authType: String) {}
})
val sslContext = SSLContext.getInstance("SSL")
sslContext.init(null, trustAllCerts, SecureRandom())
val sslParams = SSLParameters()
// This should prevent host validation
sslParams.endpointIdentificationAlgorithm = ""
httpClient = HttpClient.newBuilder()
.sslContext(sslContext)
.sslParameters(sslParams)
.build()
Но при отправке у меня есть исключение (при попытке на localhost с самозаверяющим сертификатом):
java.io.IOException: No name matching localhost found
Использование IP-адреса вместо localhost дает исключение «Отсутствуют альтернативные имена субъектов».
После некоторой отладки JDK я обнаружил, чтоsslParams
действительно игнорируются в том месте, где выдается исключение, и используется какой-то локально созданный экземпляр. Дальнейшая отладка показала, что единственным способом повлиять на алгоритм проверки имени хоста является настройкаjdk.internal.httpclient.disableHostnameVerification
системное свойство к истине. И это, кажется, решение.SSLParameters
в приведенном выше коде не имеют никакого эффекта, поэтому эту часть можно отбросить. Возможность настройки только в глобальном масштабе выглядит как серьезный недостаток дизайна в новом HttpClient API.