Spring Boot Reactive WebClient - 如何添加自定义 SSL 主机名验证

问题描述 投票:0回答:1

我正在使用 WebClient 调用另一个 API。我有一个由主机名 X 的 API 使用的证书。但是,如果我想使用与证书不同的 url 对 API 进行 https 调用,我会正确地收到错误。

问题是我将使用 docker 网络和 docker 服务发现来调用 API。这意味着我知道证书是有效的,我知道名称会不匹配(docker url 和证书 url),并且客户端应该接受这一点。

我已经尝试了以下方法,但不起作用

          .secure { sslSpec: SslProvider.SslContextSpec ->
            sslSpec
                .sslContext(SslContextBuilder.forClient()
                    .build())
                .serverNames(SNIHostName("docker-network-url"))
                .build()
          }

我知道禁用主机名检查也是一种选择,但一般来说这更不安全并且是不好的做法。

有没有办法可以验证证书名称并接受它,即使网址不同?

java spring ssl spring-webclient
1个回答
0
投票

是的,您可以通过在 SSL 握手期间指定预期的主机名,将客户端配置为接受证书,即使 URL 主机名与证书的主机名不同。就您而言,由于您将 Reactor Netty 与 WebClient 结合使用,因此您可以在 SSL 配置中设置握手主机名。这告诉 SSL 层使用指定的主机名进行 SNI(服务器名称指示)和主机名验证,即使您连接到 URL 中的不同主机名也是如此。

以下是修改代码的方法:

HttpClient httpClient = HttpClient.create()
  .secure(sslSpec -> sslSpec
    .sslContext(SslContextBuilder.forClient().build())
    .handshakeHostname("X")  // Replace "X" with the hostname in your certificate
  );
// Use this httpClient with your WebClient
WebClient webClient = WebClient.builder()
  .clientConnector(new ReactorClientHttpConnector(httpClient))
  .build();

在此代码中:

  • .handshakeHostname("X"):设置 SSL 握手期间使用的主机名。该主机名用于 SNI 和主机名验证。将“X”替换为服务器证书中存在的实际主机名。

通过设置handshakeHostname,SSL层将:

  1. 使用“X”作为SNI主机名,提示服务器提供正确的证书。
  2. 使用“X”进行主机名验证,确保证书与该主机名匹配。

此方法允许您维护安全的主机名验证,而无需完全禁用它或不加区别地接受所有证书。它有效地告诉 SSL 层,“我正在连接到主机‘docker-network-url’,但出于 SSL 目的,请将其视为‘X’。”

注意:确保将“X”替换为服务器 SSL 证书中指定的实际主机名。

© www.soinside.com 2019 - 2024. All rights reserved.