Мне нужно запросить сторонний API, который имеет несоответствие имени сертификата / DNS. Самая левая метка имени хоста, указанного в сертификате, заранее неизвестна (т. Е. CN = some-random-ha sh .example.com ), и поэтому я хочу настроить HTTP-клиент с настраиваемый верификатор имени хоста.
При использовании клиента по умолчанию Reactor Netty , полученного через HttpClient.create()
, класс HostnameChecker
не проходит проверку сертификата и вызывает исключение:
java.security.cert.CertificateException: No subject alternative DNS name matching XXX found.
at sun.security.util.HostnameChecker.matchDNS(HostnameChecker.java:214)
at sun.security.util.HostnameChecker.match(HostnameChecker.java:96)
at sun.security.ssl.X509TrustManagerImpl.checkIdentity(X509TrustManagerImpl.java:455)
at sun.security.ssl.X509TrustManagerImpl.checkIdentity(X509TrustManagerImpl.java:436)
at sun.security.ssl.X509TrustManagerImpl.checkTrusted(X509TrustManagerImpl.java:252)
at sun.security.ssl.X509TrustManagerImpl.checkServerTrusted(X509TrustManagerImpl.java:136)
at sun.security.ssl.ClientHandshaker.serverCertificate(ClientHandshaker.java:1626)
... 30 more
Этот связанный ответ предлагает реализовать SNIMatcher следующим образом:
HttpClient.create()
.secure(sslContextSpec -> sslContextSpec
.sslContext(sslContext)
.handlerConfigurator((handler) -> {
SSLEngine engine = handler.engine();
SSLParameters params = new SSLParameters();
List<SNIMatcher> matchers = new LinkedList<>();
SNIMatcher matcher = new SNIMatcher(0) {
@Override
public boolean matches(SNIServerName serverName) {
return true;
}
};
matchers.add(matcher);
params.setSNIMatchers(matchers);
engine.setSSLParameters(params);
}));
Однако, согласно Javadocs setSNIMatchers :
Этот метод полезен только для SSLSockets или SSLEngines, работающих в режиме сервера.
Следовательно, сопоставление игнорируется и, что еще хуже, приведенный выше код создает пустой набор SSLParameters
, который похоже, полностью отключает проверку SSL.
Как правильно реализовать специальный верификатор имени хоста с помощью Reactor Netty ?
Обратите внимание, что при использовании * 10 32 *Apache HTTPClient библиотека, это может быть легко достигнуто с помощью следующего:
HttpClients.custom().setSSLHostnameVerifier((hostname, session) -> ...).build();