DEBUG.WIKI
丽萨主机;为跨境业务选好 IP;原生 / 住宅 IP · 按套餐选择;查看 IP →
V.PS:让项目靠近用户,亚太、欧洲、北美 KVM VPS
OnlineSIM:在线接收短信,虚拟号码租用

Spring Boot 3.5.14 配置客户端证书后,SNI 日志报 SslProvider 空指针

Reactor Netty 服务启用 SSL bundle 与客户端证书验证后,未映射的 SNI 名称可能触发空指针。核对默认证书回退与 3.5.15 修正,保留双向 TLS 验证。

Spring Boot 3.5.14 的 Reactor Netty HTTPS 服务配置了 SSL bundle,并启用了客户端证书验证,接到带 SNI 的连接后,日志出现下面的空指针:

Cannot invoke "reactor.netty.tcp.SslProvider.getSslContext()" because "sslProvider" is null

调用栈经过 SniProvider$SniHandler.onLookupComplete。在 Boot 3.5.14、Reactor Netty 1.2.17、Java 21 的组合中,客户端发送的服务器名称没有匹配 server.ssl.server-name-bundles 时,可能走到这条路径。没有配置额外的名称映射,也属于“没有匹配项”。

先分清日志异常与连接结果:这条空指针可能被下层处理捕获,握手仍退回默认 SSL 上下文,不能仅凭日志就断定所有请求都失败。反过来,接口偶尔能返回,也不等于证书选择和客户端身份验证已经符合预期。

找不到名称时,本应使用默认 bundle

server.ssl.bundle 指定默认的服务端 SSL bundle,server.ssl.server-name-bundles 为具体 SNI 名称选择其他 bundle。客户端没有发送名称,或发送的名称没有对应的专用配置,都需要有明确的默认处理。

3.5.14 这条实现对非空服务器名称直接查询映射;查不到时返回 null,随后代码继续读取它的 SSL 上下文,便产生异常。配置客户端证书验证或信任材料时会涉及这里的 SNI provider 选择。它与客户端漏发 SNI、证书 SAN 不匹配、客户端证书链不完整是不同问题。

Spring Boot 3.5.15 已将未命中映射的情况回退到默认 provider。使用 3.5.x 的应用应通过现有 Boot 依赖管理入口采用包含该修正、且符合项目兼容要求的正式维护版本。3.5.15 是这条修正的首个 3.5.x 正式版本,不意味着已经使用更新维护版的项目要退回它。

保留依赖锁定文件、原部署包及 SSL 配置,再核对最终解析和实际启动的 Boot、Reactor Netty 版本。只单独替换一个 Netty jar,容易造成平台依赖错配,也未必改到 Boot 的 provider 选择代码。

暂不能升级时,可以为已知名称显式映射

如果服务只接受一组已经确定的域名,可在现有配置中为这些名称显式指定 bundle。下面假设名为 server 的 bundle 已配置好服务端证书、私钥和所需信任材料,证书覆盖 app.example.com,并继续要求客户端证书:

server:
  ssl:
    bundle: server
    client-auth: need
    server-name-bundles:
      - server-name: app.example.com
        bundle: server

这是合并到原配置的片段,不能覆盖其他域名已有的 bundle。示例域名应替换成实际提供服务的名称,不能把任意客户端传来的名称都当成可信域名。

显式映射只能避开这些已知名称的未命中路径;其他名称仍可能触发旧实现的问题。因此它适合边界清楚的临时处理,不能代替版本修正。不要删除 truststore、将 client-auth: need 改成免认证,或要求客户端跳过服务器证书验证来压住日志。

同时核对证书选择和客户端身份

在隔离环境分别覆盖已映射名称、没有专用映射的合法服务名称和不发送 SNI 的连接,检查实际返回的证书及名称校验结果。需要双向 TLS 的入口还要分别使用合法客户端证书、未受信任证书和不带证书的请求,确认只有应获准的身份能进入业务。

升级后,未映射名称不应再因读取空 SslProvider 产生上述异常;不合法的名称、证书或客户端身份仍应按原策略被拒绝。若日志变成信任链或证书名称错误,应沿对应的验证失败继续检查,不要再用添加 SNI 映射掩盖它。