我正在使用 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()
}
我知道禁用主机名检查也是一种选择,但一般来说这更不安全并且是不好的做法。
有没有办法可以验证证书名称并接受它,即使网址不同?
是的,您可以通过在 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,SSL层将:
此方法允许您维护安全的主机名验证,而无需完全禁用它或不加区别地接受所有证书。它有效地告诉 SSL 层,“我正在连接到主机‘docker-network-url’,但出于 SSL 目的,请将其视为‘X’。”
注意:确保将“X”替换为服务器 SSL 证书中指定的实际主机名。