Spring Cloud Gateway全局过滤器中如何获取Principal?
Spring Cloud Gateway全局过滤器中获取Principal的正确方式
在WebFlux响应式编程里,Mono/Flux是懒加载的——只有当整个响应式链被Spring框架订阅时,逻辑才会执行。你手动调用subscribe()相当于创建了一个脱离框架管理的独立链,自然不会触发执行。下面是两种场景下的正确实现方式:
1. 请求前置阶段获取(转发前处理)
如果要在转发请求前拿到Principal并做处理,得把获取逻辑整合到返回的响应式链中,用flatMap串联操作:
public class MyGlobalFilter implements GlobalFilter { @Override public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) { return exchange.getPrincipal() .map(principal -> { // 这里写你的处理逻辑,比如打印用户信息、存到exchange属性里 System.out.println("当前登录用户:" + principal.getName()); exchange.getAttributes().put("CURRENT_USER", principal); return exchange; }) // 继续执行后续过滤器和请求转发 .flatMap(chain::filter); } }
2. 请求后置阶段获取(转发后处理)
这就是你已经试成功的方式,适合在请求完成后处理Principal:
public class MyGlobalFilter implements GlobalFilter { @Override public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) { // 先执行请求转发,完成后再处理Principal return chain.filter(exchange) .then(exchange.getPrincipal()) .map(principal -> { // 后置逻辑,比如记录请求完成日志 System.out.println("请求处理完成,用户:" + principal.getName()); return principal; }) // 转换为Mono<Void>符合方法返回值要求 .then(); } }
关键提醒
- 绝对不要在过滤器里手动调用
subscribe(),这会脱离Spring响应式上下文,要么逻辑不执行,要么引发线程安全问题。 - 如果后续过滤器或路由需要复用Principal,可以把它存到
ServerWebExchange的属性中,之后用exchange.getAttribute("CURRENT_USER")就能获取到。
内容的提问来源于stack exchange,提问作者Mr R
相关产品推荐
相关产品推荐

