繁体   English   中英

Spring Webflux - 基于 TLSv1.2 的 WebClient

[英]Spring Webflux - WebClient over TLSv1.2

关于 Spring Webflux WebClient 的小问题,尤其是如何配置一个使用 TLSv1.2 发送出站请求。

我的应用是 Spring Webflux 2.4.2,其中启用了 HTTP/2、SSL、mTLS 和 TLSv1.3。

server.ssl.enabled-protocols=TLSv1.3
server.http2.enabled=true
server.ssl.client-auth=need
server.ssl.enabled=true
server.ssl.key-alias=alias
server.ssl.key-password=
server.ssl.key-store-password=
server.ssl.key-store-provider=SUN
server.ssl.key-store-type=JKS
server.ssl.key-store=/keystore.p12
server.ssl.trust-store-password=
server.ssl.trust-store-provider=SUN
server.ssl.trust-store-type=JKS
server.ssl.trust-store=/truststore.p12

请注意,它是 TLSv1.3,而不是设置上的 TLSv1,2。

当我创建 WebClient 的实例时:

getWebClient().mutate().baseUrl("https://some-server.com").build().post().uri("/some/route").retrieve().bodyToMono(String.class);

 @Bean
    @Primary
    public WebClient getWebClient() {
        return WebClient.create().mutate().defaultHeader(HttpHeaders.CONTENT_TYPE, MediaType.APPLICATION_JSON_VALUE, HttpHeaders.ACCEPT, MediaType.APPLICATION_JSON_VALUE).clientConnector(new ReactorClientHttpConnector(HttpClient.create().secure(sslContextSpec -> sslContextSpec.sslContext(getSslContextBuilder())))).build();
    }


    public SslContextBuilder getSslContextBuilder() {
        try {
            final KeyManagerFactory keyManagerFactory = KeyManagerFactory.getInstance(KeyManagerFactory.getDefaultAlgorithm());
            try (InputStream file = new FileInputStream(keyStorePath)) {
                final KeyStore keyStore = KeyStore.getInstance(keyStoreType);
                keyStore.load(file, keyStorePassPhrase.toCharArray());
                keyManagerFactory.init(keyStore, keyPassPhrase.toCharArray());
            }

            final TrustManagerFactory trustManagerFactory = TrustManagerFactory.getInstance(TrustManagerFactory.getDefaultAlgorithm());
            try (InputStream trustStoreFile = new FileInputStream(trustStorePath)) {
                final KeyStore trustStore = KeyStore.getInstance(trustStoreType);
                trustStore.load(trustStoreFile, trustStorePassPhrase.toCharArray());
                trustManagerFactory.init(trustStore);
            }

            final ApplicationProtocolConfig applicationProtocolConfig = new ApplicationProtocolConfig(ApplicationProtocolConfig.Protocol.ALPN, ApplicationProtocolConfig.SelectorFailureBehavior.NO_ADVERTISE, ApplicationProtocolConfig.SelectedListenerFailureBehavior.ACCEPT, ApplicationProtocolNames.HTTP_2, ApplicationProtocolNames.HTTP_1_1);
            return SslContextBuilder.forClient().applicationProtocolConfig(applicationProtocolConfig).keyManager(keyManagerFactory).trustManager(InsecureTrustManagerFactory.INSTANCE);
        } catch (CertificateException | NoSuchAlgorithmException | IOException | KeyStoreException | UnrecoverableKeyException e) {
            return null;
        }
    }

并使用它向启用了 TLSv1.3 的服务器发送请求,它工作正常,非常高兴。

但是,我需要与之交互的一些服务器要么具有旧的/不同的 JDK 版本,要么启用了 TLSv1.2(我不拥有那些第三方 API)。

因为我得到:

io.netty.handler.codec.DecoderException: javax.net.ssl.SSLHandshakeException: extension (5) should not be presented in certificate_request

在 SO 中研究后,我发现我可以配置这样的。

@SpringBootApplication
public class MyApplication {

    public static void main(String[] args) {
        System.setProperty("jdk.tls.client.protocols", "TLSv1.2");
        SpringApplication.run(MyApplication.class);
    }

令人惊讶的是,问题已解决(不知道为什么)。

我的问题是:我可以简单地在代码级别上使用 WebClient 实现相同的功能,而不是设置系统属性吗?

谢谢

截至今天, System.setProperty("jdk.tls.client.protocols", "TLSv1.2"); 是解决方案

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM