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

为何ReactiveSecurityContextHolder获取认证主体为null?如何获取原始Token?

ReactiveSecurityContextHolder获取认证主体为null的原因与解决方法

问题描述

编写了如下方法:

@GetMapping("/foo")
public void foo(JwtAuthenticationToken token) throws ExecutionException, InterruptedException {
    Object object = ReactiveSecurityContextHolder.getContext()
            .map(securityContext -> securityContext.getAuthentication().getPrincipal())
            .toFuture()
            .get();
    System.out.println(object);
}

方法参数的JwtAuthenticationToken已成功注入且不为null,但通过ReactiveSecurityContextHolder获取的认证主体结果为null。

问题原因

  1. 阻塞调用破坏反应式上下文:Spring WebFlux的ReactiveSecurityContextHolder依赖Reactor的Context传递安全信息,而.toFuture().get()是阻塞式同步调用,会脱离原有的反应式执行上下文,导致ReactiveSecurityContextHolder无法获取到绑定的安全上下文,最终返回null。
  2. 方法类型不符合反应式模型:当前方法是同步的void类型,不匹配WebFlux的反应式编程模型,无法正确维护上下文传递链。

解决方案

方案一:改用反应式方法(推荐)

将方法返回类型改为Mono<Void>,保持所有操作在反应式链中执行,确保上下文正确传递:

@GetMapping("/foo")
public Mono<Void> foo(JwtAuthenticationToken token) {
    return ReactiveSecurityContextHolder.getContext()
            .map(securityContext -> securityContext.getAuthentication().getPrincipal())
            .doOnNext(principal -> System.out.println(principal))
            .then();
}

方案二:直接使用已注入的JwtAuthenticationToken

既然JwtAuthenticationToken已经作为参数注入,可直接通过它获取主体,无需再从ReactiveSecurityContextHolder获取,代码更简洁:

@GetMapping("/foo")
public Mono<Void> foo(JwtAuthenticationToken token) {
    Object principal = token.getPrincipal();
    System.out.println(principal);
    return Mono.empty();
}

注意事项

WebFlux中禁止使用.get()、block()这类阻塞式方法,它们不仅会导致上下文丢失,还会严重影响应用的性能和扩展性。

相关话题:如何在Spring WebFlux中获取JWT令牌值?(用于与Minio STS令牌交换)

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.07 11:31:13