Spring WebClient主机名校验默认状态及验证方法问询
1. WebClient 主机名校验默认状态
在你使用的Spring Boot 3.1.5(对应Spring Framework 6.0.x)搭配Reactor-Netty + Netty 4.1.100环境下,WebClient的SSL主机名校验默认是开启的。
原因是:Spring WebClient基于Reactor Netty HttpClient构建,而Reactor Netty默认会使用JDK标准的SSL上下文,JDK原生SSLContext默认就会强制执行主机名匹配校验(符合RFC 2818规范)。Netty原生API可能需要手动配置主机名校验,但Spring在封装WebClient时已经默认启用了该机制,无需额外配置。
2. 验证WebClient正在执行主机名校验的方法
最直接的方式是构造一个证书主机名不匹配的测试场景,观察WebClient的请求结果:
步骤1:搭建测试服务
生成一张SSL证书,将证书的CN(通用名称)或SAN(主题备用名称)设置为fake.example.com,然后启动一个HTTPS服务,绑定到localhost或其他与证书不匹配的域名/IP。
步骤2:编写WebClient测试代码
import org.springframework.web.reactive.function.client.WebClient; import reactor.netty.http.client.SslHandshakeException; public class WebClientHostnameVerifyTest { public static void main(String[] args) { WebClient webClient = WebClient.create(); try { // 请求地址与证书主机名不匹配 webClient.get() .uri("https://localhost:8443/api/test") .retrieve() .bodyToMono(String.class) .block(); } catch (SslHandshakeException e) { // 捕获到握手异常,说明主机名校验生效 System.out.println("主机名校验触发,异常详情:" + e.getMessage()); } } }
验证结果
如果运行代码后抛出SslHandshakeException,异常信息包含类似No subject alternative DNS name matching localhost found或hostname in certificate didn't match的内容,即可证明WebClient正在执行主机名校验。
另外,也可以通过查看Reactor Netty的配置逻辑确认:默认情况下,WebClient的底层HttpClient不会调用sslContextBuilder.hostnameVerifier(NoopHostnameVerifier.INSTANCE)这类禁用校验的API,进一步说明校验处于启用状态。
关于漏洞扫描工具的误报
部分扫描工具可能仅检测Netty原生的默认配置(Netty原生确实未强制开启主机名校验),但Spring WebClient在封装时已经默认启用了该机制,因此实际环境中不存在CWE-295漏洞,可通过上述测试结果向扫描工具提交误报申诉。
内容的提问来源于stack exchange,提问作者Robert Wynkoop

