Custom Reactor Netty Верификатор имени хоста - PullRequest
0 голосов
/ 11 января 2020

Мне нужно запросить сторонний 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();
...