You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Spring Boot Webflux WebClient经HTTP代理双向TLS认证失败

HTTP代理下双向TLS认证握手失败问题

我有一个基于Spring Boot、Webflux的Java应用,使用搭载Reactor连接器的WebClient向外部服务器发起HTTPS请求。该服务器要求双向TLS认证,无代理时已通过配置SslContext实现正常运行,但配置HTTP代理(测试过tinyproxy和squid)后出现SSL握手错误。

无代理时正常运行的WebClient代码

String keystore = Files.readString(Paths.get("/my-keystore.p12"));
InputStream keystoreInputStream = new ByteArrayInputStream(keystore);
KeyStore keyStore = KeyStore.getInstance("PKCS12");

keyStore.load(keystoreInputStream, "keystore-pass");

KeyManagerFactory keyManagerFactory = KeyManagerFactory.getInstance(KeyManagerFactory.getDefaultAlgorithm());

keyManagerFactory.init(keyStore, "my-pass");

SslContext sslContext = SslContextBuilder.forClient()
        .keyManager(keyManagerFactory)
        .build();

WebClient.Builder builder = WebClient.builder()
    .baseUrl("external-service-url")
    .clientConnector(
            new ReactorClientHttpConnector(
                    HttpClient.create()
                            .secure(sslSpec -> sslSpec.sslContext(sslContext))
                            .proxy(
                                 proxySpec -> proxySpec
                                .type(ProxyProvider.Proxy.HTTP)
                                .host("my-proxy-host")
                                .port(Integer.parseInt("3128"))
                    )
            )
    );

无代理时关键SSL日志(开启-Djavax.net.debug=all)

javax.net.ssl|WARNING|10 51|reactor-http-epoll-5|2024-06-03 15:07:30.250 CEST|SignatureScheme.java:434|Unsupported signature scheme: dsa_sha384
javax.net.ssl|WARNING|10 51|reactor-http-epoll-5|2024-06-03 15:07:30.250 CEST|SignatureScheme.java:434|Unsupported signature scheme: dsa_sha512
javax.net.ssl|DEBUG|10 51|reactor-http-epoll-5|2024-06-03 15:07:30.250 CEST|SunX509KeyManagerImpl.java:388|matching alias: my-cert

启用代理后的关键SSL日志

javax.net.ssl|WARNING|10 01|reactor-http-epoll-5|2024-06-03 15:05:32.166 CEST|SignatureScheme.java:434|Unsupported signature scheme: dsa_sha384
javax.net.ssl|WARNING|10 01|reactor-http-epoll-5|2024-06-03 15:05:32.166 CEST|SignatureScheme.java:434|Unsupported signature scheme: dsa_sha512
javax.net.ssl|ALL|10 01|reactor-http-epoll-5|2024-06-03 15:05:32.166 CEST|X509Authentication.java:249|No X.509 cert selected for RSA
javax.net.ssl|WARNING|10 01|reactor-http-epoll-5|2024-06-03 15:05:32.166 CEST|CertificateRequest.java:821|Unavailable authentication scheme: rsa_pkcs1_sha256
javax.net.ssl|ALL|10 01|reactor-http-epoll-5|2024-06-03 15:05:32.166 CEST|X509Authentication.java:249|No X.509 cert selected for DSA
javax.net.ssl|WARNING|10 01|reactor-http-epoll-5|2024-06-03 15:05:32.166 CEST|CertificateRequest.java:821|Unavailable authentication scheme: dsa_sha256
javax.net.ssl|ALL|10 01|reactor-http-epoll-5|2024-06-03 15:05:32.167 CEST|X509Authentication.java:249|No X.509 cert selected for EC
javax.net.ssl|WARNING|10 01|reactor-http-epoll-5|2024-06-03 15:05:32.167 CEST|CertificateRequest.java:821|Unavailable authentication scheme: ecdsa_secp256r1_sha256
javax.net.ssl|ALL|10 01|reactor-http-epoll-5|2024-06-03 15:05:32.167 CEST|X509Authentication.java:249|No X.509 cert selected for RSA
javax.net.ssl|WARNING|10 01|reactor-http-epoll-5|2024-06-03 15:05:32.167 CEST|CertificateRequest.java:821|Unavailable authentication scheme: rsa_pkcs1_sha384
javax.net.ssl|ALL|10 01|reactor-http-epoll-5|2024-06-03 15:05:32.167 CEST|X509Authentication.java:249|No X.509 cert selected for EC
javax.net.ssl|WARNING|10 01|reactor-http-epoll-5|2024-06-03 15:05:32.167 CEST|CertificateRequest.java:821|Unavailable authentication scheme: ecdsa_secp384r1_sha384
javax.net.ssl|ALL|10 01|reactor-http-epoll-5|2024-06-03 15:05:32.167 CEST|X509Authentication.java:249|No X.509 cert selected for RSA
javax.net.ssl|WARNING|10 01|reactor-http-epoll-5|2024-06-03 15:05:32.167 CEST|CertificateRequest.java:821|Unavailable authentication scheme: rsa_pkcs1_sha512
javax.net.ssl|ALL|10 01|reactor-http-epoll-5|2024-06-03 15:05:32.167 CEST|X509Authentication.java:249|No X.509 cert selected for EC
javax.net.ssl|WARNING|10 01|reactor-http-epoll-5|2024-06-03 15:05:32.167 CEST|CertificateRequest.java:821|Unavailable authentication scheme: ecdsa_secp521r1_sha512
javax.net.ssl|ALL|10 01|reactor-http-epoll-5|2024-06-03 15:05:32.167 CEST|X509Authentication.java:249|No X.509 cert selected for RSA
javax.net.ssl|WARNING|10 01|reactor-http-epoll-5|2024-06-03 15:05:32.167 CEST|CertificateRequest.java:821|Unavailable authentication scheme: rsa_pkcs1_sha1
javax.net.ssl|ALL|10 01|reactor-http-epoll-5|2024-06-03 15:05:32.167 CEST|X509Authentication.java:249|No X.509 cert selected for DSA
javax.net.ssl|WARNING|10 01|reactor-http-epoll-5|2024-06-03 15:05:32.167 CEST|CertificateRequest.java:821|Unavailable authentication scheme: dsa_sha1
javax.net.ssl|ALL|10 01|reactor-http-epoll-5|2024-06-03 15:05:32.167 CEST|X509Authentication.java:249|No X.509 cert selected for EC
javax.net.ssl|WARNING|10 01|reactor-http-epoll-5|2024-06-03 15:05:32.167 CEST|CertificateRequest.java:821|Unavailable authentication scheme: ecdsa_sha1
javax.net.ssl|WARNING|10 01|reactor-http-epoll-5|2024-06-03 15:05:32.167 CEST|CertificateRequest.java:831|No available authentication scheme
javax.net.ssl|DEBUG|10 01|reactor-http-epoll-5|2024-06-03 15:05:32.167 CEST|SSLEngineInputRecord.java:176|Raw read (
  0000: XXXXXXXXXX                       .........
)
javax.net.ssl|DEBUG|10 01|reactor-http-epoll-5|2024-06-03 15:05:32.167 CEST|SSLEngineInputRecord.java:213|READ: TLSv1.2 handshake, length = 4
javax.net.ssl|DEBUG|10 01|reactor-http-epoll-5|2024-06-03 15:05:32.168 CEST|ServerHelloDone.java:151|Consuming ServerHelloDone handshake message (
<empty>
)
javax.net.ssl|DEBUG|10 01|reactor-http-epoll-5|2024-06-03 15:05:32.168 CEST|CertificateMessage.java:299|No X.509 certificate for client authentication, use empty Certificate message instead
javax.net.ssl|DEBUG|10 01|reactor-http-epoll-5|2024-06-03 15:05:32.168 CEST|CertificateMessage.java:330|Produced client Certificate handshake message (
"Certificates": <empty list>
)
javax.net.ssl|DEBUG|10 01|reactor-http-epoll-5|2024-06-03 15:05:32.171 CEST|ECDHClientKeyExchange.java:407|Produced ECDHE ClientKeyExchange handshake message (
"ECDH ClientKeyExchange": {
  "ecdh public": {
    XXXXXXX                                          .
  },
}
)
javax.net.ssl|DEBUG|10 01|reactor-http-epoll-5|2024-06-03 15:05:32.175 CEST|ChangeCipherSpec.java:115|Produced ChangeCipherSpec message
javax.net.ssl|DEBUG|10 01|reactor-http-epoll-5|2024-06-03 15:05:32.175 CEST|Finished.java:396|Produced client Finished handshake message (
"Finished": {
  "verify data": {
    0000: XXXXXXX
  }'
}
)
javax.net.ssl|DEBUG|10 01|reactor-http-epoll-5|2024-06-03 15:05:32.175 CEST|SSLEngineOutputRecord.java:530|WRITE: TLSv1.2 handshake, length = 77
javax.net.ssl|DEBUG|10 01|reactor-http-epoll-5|2024-06-03 15:05:32.176 CEST|SSLEngineOutputRecord.java:551|Raw write (
  0000: XXXXXX                                            ..
)
javax.net.ssl|DEBUG|10 01|reactor-http-epoll-5|2024-06-03 15:05:32.176 CEST|SSLEngineOutputRecord.java:530|WRITE: TLSv1.2 change_cipher_spec, length = 1
javax.net.ssl|DEBUG|10 01|reactor-http-epoll-5|2024-06-03 15:05:32.176 CEST|SSLEngineOutputRecord.java:551|Raw write (
  0000: XXXXXXX                                ......
)
javax.net.ssl|DEBUG|10 01|reactor-http-epoll-5|2024-06-03 15:05:32.176 CEST|SSLEngineOutputRecord.java:530|WRITE: TLSv1.2 handshake, length = 16
javax.net.ssl|DEBUG|10 01|reactor-http-epoll-5|2024-06-03 15:05:32.176 CEST|SSLCipher.java:1773|Plaintext before ENCRYPTION (
  0000: XXXXX
)
javax.net.ssl|DEBUG|10 01|reactor-http-epoll-5|2024-06-03 15:05:32.176 CEST|SSLEngineOutputRecord.java:551|Raw write (
  0000: XXXXX
)
javax.net.ssl|DEBUG|10 01|reactor-http-epoll-5|2024-06-03 15:05:32.218 CEST|SSLEngineInputRecord.java:176|Raw read (
  0000: XXXXXXX                            ......(
)
javax.net.ssl|DEBUG|10 01|reactor-http-epoll-5|2024-06-03 15:05:32.218 CEST|SSLEngineInputRecord.java:213|READ: TLSv1.2 alert, length = 2
javax.net.ssl|DEBUG|10 01|reactor-http-epoll-5|2024-06-03 15:05:32.219 CEST|Alert.java:238|Received alert message (
"Alert": {
  "level"      : "fatal",
  "description": "handshake_failure"
}
)

从日志能看出,启用代理后JVM找不到用于认证的证书,但不清楚具体原因,也不确定HTTP代理环境下是否支持双向TLS认证这种方式。

内容的提问来源于stack exchange,提问作者Benoit

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.22 19:59:49