Как отключить проверку имени хоста в весеннем веб-клиенте? - PullRequest
1 голос
/ 17 мая 2019

Я использую весенний инструмент webflux для вызова API.Адрес сервера API - HTTPS, и это IP-адрес без имени домена.Мне нужно отключить проверку имени хоста в веб-клиенте.Теперь исключение выглядит следующим образом

Caused by: java.security.cert.CertificateException: No subject alternative names matching IP address 180.101.147.89 found
    at sun.security.util.HostnameChecker.matchIP(HostnameChecker.java:168) ~[na:1.8.0_211]
    at sun.security.util.HostnameChecker.match(HostnameChecker.java:94) ~[na:1.8.0_211]
    at sun.security.ssl.X509TrustManagerImpl.checkIdentity(X509TrustManagerImpl.java:461) ~[na:1.8.0_211]
    at sun.security.ssl.X509TrustManagerImpl.checkIdentity(X509TrustManagerImpl.java:442) ~[na:1.8.0_211]
    at sun.security.ssl.X509TrustManagerImpl.checkTrusted(X509TrustManagerImpl.java:260) ~[na:1.8.0_211]
    at sun.security.ssl.X509TrustManagerImpl.checkServerTrusted(X509TrustManagerImpl.java:144) ~[na:1.8.0_211]
    at sun.security.ssl.ClientHandshaker.serverCertificate(ClientHandshaker.java:1626) ~[na:1.8.0_211]
    ... 28 common frames omitted
@Bean
    public WebClient telcomWebclient(WebClient.Builder webClientBuilder,
                                     @Value("${telcom.api.host}") String telcomApiHost,
                                     @Value("${telcom.api.certificate-name}") String telcomApiCertificateName,
                                     @Value("${telcom.api.certificate-store-pass}") String telcomApiCertificateStorePass) {
        try {
            KeyStore selfCert = KeyStore.getInstance("pkcs12");
            selfCert.load(getClass().getResourceAsStream("/cert/outgoing.CertwithKey.pkcs12"), "IoM@1234".toCharArray());
            KeyManagerFactory kmf = KeyManagerFactory.getInstance("sunx509");
            kmf.init(selfCert, "IoM@1234".toCharArray());

            KeyStore caCert = KeyStore.getInstance("jks");
            caCert.load(getClass().getResourceAsStream("/cert/" + telcomApiCertificateName), telcomApiCertificateStorePass.toCharArray());
            TrustManagerFactory tmf = TrustManagerFactory.getInstance("sunx509");
            tmf.init(caCert);

            SslContext sslContext = SslContextBuilder.forClient()
                    .keyManager(kmf)
                    .trustManager(tmf)
                    .build();
            HttpClient httpClient = HttpClient.create().create().secure(sslContextSpec -> sslContextSpec.sslContext(sslContext));
            ClientHttpConnector clientHttpConnector = new ReactorClientHttpConnector(httpClient);
            return webClientBuilder.clientConnector(clientHttpConnector).baseUrl(telcomApiHost).build();
        } catch (KeyStoreException | IOException | NoSuchAlgorithmException | CertificateException | UnrecoverableKeyException e) {
            log.error("Config webclient,error occurs", e);
            System.exit(-1);
        }
        return null;
    }

1 Ответ

2 голосов
/ 03 июня 2019

Помимо полного отключения проверки SSL, ( КОТОРОЕ Я НЕ РЕКОМЕНДУЮ ), передав InsecureTrustManagerFactory.INSTANCE следующим образом:

SslContext sslContext = SslContextBuilder.forClient()
                    .keyManager(kmf)
                    .trustManager(InsecureTrustManagerFactory.INSTANCE)
                    .build();

Вы можете настроить HttpClient для существенной отмены проверки имени хоста, настроив пользовательский SNIMatcher , как показано ниже:

HttpClient.create().create().secure(sslContextSpec -> sslContextSpec
    .sslContext(sslContext)
    .handlerConfigurator(sslHandler -> 
        SSLEngine engine = handler.engine();
        //engine.setNeedClientAuth(true);
        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);
);

Я проверил это и убедился, что оно работает. Надеюсь, это поможет!

Это было вдохновлено ответом здесь: Сконфигурируйте HostnameVerifier с реактивной сеткой для spring-webflux WebClient

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...