为何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。
问题原因
- 阻塞调用破坏反应式上下文:Spring WebFlux的
ReactiveSecurityContextHolder依赖Reactor的Context传递安全信息,而.toFuture().get()是阻塞式同步调用,会脱离原有的反应式执行上下文,导致ReactiveSecurityContextHolder无法获取到绑定的安全上下文,最终返回null。 - 方法类型不符合反应式模型:当前方法是同步的
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
相关产品推荐
相关产品推荐

