Spring WebFlux中如何通过ReactiveSecurityContextHolder获取JWT?
如何在Spring WebFlux中通过ReactiveSecurityContextHolder获取JWT令牌
首先明确:在Spring WebFlux的响应式模型中,绝对不能使用block()等阻塞方法,这会破坏响应式链,导致ReactiveSecurityContextHolder的上下文丢失,同时违反非阻塞设计原则,这也是你遇到异常或空值的核心原因。
ReactiveSecurityContextHolder的上下文绑定在Reactor流的Context中,只有在Mono/Flux的操作链内才能正确访问,以下是正确的实现方式:
1. 封装可复用的上下文获取工具
编写工具类统一处理JWT认证信息的获取:
public class ReactiveSecurityUtils { // 获取当前请求的JWT认证令牌 public static Mono<JwtAuthenticationToken> getCurrentJwtAuth() { return ReactiveSecurityContextHolder.getContext() .map(SecurityContext::getAuthentication) .cast(JwtAuthenticationToken.class); } }
2. 在响应式流中使用
所有需要获取JWT信息的操作必须嵌入Mono/Flux的操作链中,比如在Controller层:
@RestController public class UserController { private static final String USER_MAIN_ID_TOKEN = "user_main_id"; @GetMapping("/user/main-id") public Mono<String> getUserMainId() { return ReactiveSecurityUtils.getCurrentJwtAuth() .map(jwtAuth -> jwtAuth.getTokenAttributes().get(USER_MAIN_ID_TOKEN).toString()); } }
在Service层复用同样要保持响应式:
@Service public class UserService { private static final String USER_MAIN_ID_TOKEN = "user_main_id"; public Mono<User> getCurrentUser() { return ReactiveSecurityUtils.getCurrentJwtAuth() .map(jwtAuth -> (String) jwtAuth.getTokenAttributes().get(USER_MAIN_ID_TOKEN)) .flatMap(this::getUserById); // 调用其他响应式业务方法 } private Mono<User> getUserById(String userId) { // 模拟从数据库获取用户的响应式操作 return Mono.just(new User(userId)); } }
3. 为什么之前的方式无效?
- 非响应式的
Supplier无法访问Reactor流的Context,直接调用get()会因上下文未绑定返回null - 使用
block()会强制中断响应式链,导致上下文丢失,同时触发WebFlux的阻塞操作异常 - 所有依赖
ReactiveSecurityContextHolder的操作,必须处于Mono/Flux的操作链中,才能继承当前请求的上下文
内容的提问来源于stack exchange,提问作者lemario
相关产品推荐
相关产品推荐

