我正在使用spring webflux Webclient工具来调用API.API服务器地址是HTTPS,它是一个没有域名的IP地址.我需要在webclient中禁用主机名验证.现在例外如下
I am using the spring webflux webclient tool to call the API. The API server address is HTTPS, and it is an IP address without a domain name. I need to disable the hostname validation in webclient. The exception now is as follows
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; } 推荐答案除了完全禁用SSL验证,(我不建议)通过传入 InsecureTrustManagerFactory.INSTANCE 像这样的代码:
Aside from disabling SSL verification entirely, (WHICH I DON'T RECOMMEND) by passing in InsecureTrustManagerFactory.INSTANCE like this:
SslContext sslContext = SslContextBuilder.forClient() .keyManager(kmf) .trustManager(InsecureTrustManagerFactory.INSTANCE) .build();您可以通过配置自定义 SNIMatcher 如下:
You can configure the HttpClient to essentially override the hostname verification by configuring a custom SNIMatcher as below:
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); );我已经对此进行了测试并验证了它的有效性.我希望这会有所帮助!
I have tested this and verified it worked. I hope this helps!
这是受这里答案的启发:使用以下命令配置HostnameVerifierspring-webflux WebClient的反应堆净额
This was inspired by the answer here: Configure HostnameVerifier with reactor netty for spring-webflux WebClient
更多推荐
如何在Spring WebClient中禁用主机名验证?
发布评论