WebFlux微服务中ReactiveSecurityContextHolder获取上下文为空问题
解决WebFlux中ReactiveSecurityContextHolder获取上下文为空的问题
我来帮你搞定这个坑!核心问题其实是WebClient请求头的配置时机不对——你现在是在WebClient初始化阶段就尝试获取SecurityContext,但这个时候还没有任何请求上下文,自然拿不到令牌;而调试时flatMap里能看到上下文,是因为那时候已经处于请求处理的响应式流中,上下文已经绑定好了。
问题根源拆解
WebClient.builder().defaultHeaders(...)里的逻辑是同步执行的,也就是在WebClient实例创建的时候就跑了,这时候还没进入任何请求的响应式上下文链,ReactiveSecurityContextHolder.getContext()返回的是空Mono。但你需要的是在每次请求发送时,动态获取当前请求的SecurityContext来设置请求头,这和defaultHeaders的执行时机完全不匹配。
解决方案:用ExchangeFilterFunction动态注入请求头
我们需要把添加请求头的逻辑放到ExchangeFilterFunction中,它会在每次请求发起时执行,这时当前请求的SecurityContext已经被正确传播到响应式上下文中,就能正常拿到AuthHeaders了。
修改后的WebClient构建代码
// 替换原来的WebClient构建逻辑 WebClient.builder() .baseUrl(url) .filter(loggingFilter) // 新增动态请求头过滤器 .filter((clientRequest, nextFilter) -> SecurityUtils.getAuthHeaders() .flatMap(authHeaders -> { // 基于当前上下文的认证信息修改请求 ClientRequest modifiedRequest = ClientRequest.from(clientRequest) .header(REQUEST_ID, authHeaders.getRequestId()) .header(AUTHORIZATION, authHeaders.getAuthToken()) .build(); return nextFilter.exchange(modifiedRequest); }) // 可选:处理没有拿到AuthHeaders的情况,比如返回未授权错误 .switchIfEmpty(Mono.error(new UnauthorizedException("No authentication context found"))) ) .build();
额外注意点
- 确保你的请求处理链路全程是响应式的,不要用
block()这类阻塞操作,否则会打断SecurityContext的上下文传播。 - 如果
SecurityUtils.getAuthHeaders()可能返回空(比如未认证请求),一定要添加switchIfEmpty处理,避免请求带着空头发送出去。
这样修改后,每次WebClient发送请求时,都会先从当前请求的SecurityContext里获取到正确的AuthHeaders,再给请求加上对应的头,就能完全符合你的预期了。
内容的提问来源于stack exchange,提问作者Artjom Nikulin
相关产品推荐
相关产品推荐

