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

如何让CacheRequestBodyGatewayFilterFactory优先于Spring Security过滤器执行

在Spring Cloud Gateway中让CacheRequestBodyGatewayFilterFactory在Spring Security过滤器前执行

问题背景

我正在开发集成Spring Security的Spring Cloud Gateway项目,需要用官方的CacheRequestBodyGatewayFilterFactory缓存请求体——就算安全过滤器返回401/403拒绝请求,也能拿到请求体做分析和日志记录。

当前Security简化配置如下:

@Configuration
public class SecurityConfig {

    @Bean
    public SecurityWebFilterChain springSecurityFilterChain(ServerHttpSecurity http) {
        return http
            .csrf(ServerHttpSecurity.CsrfSpec::disable)
            .authorizeExchange(ex -> ex.anyExchange().authenticated())
            .addFilterAt(customFilter(), SecurityWebFiltersOrder.FIRST)
            .addFilterAt(authenticationWebFilter(...), SecurityWebFiltersOrder.AUTHENTICATION)
            .addFilterAt(authorizationWebFilter(...), SecurityWebFiltersOrder.AUTHORIZATION)
            .build();
    }

}

现在的问题是:如果早期安全过滤器(比如认证过滤器)执行失败,作为路由过滤器的CacheRequestBodyGatewayFilterFactory根本不会触发,拿不到请求体做后续分析和日志。

核心需求

  • 让CacheRequestBodyGatewayFilterFactory(或其缓存逻辑)在Spring Security所有过滤器之前运行
  • 无论认证/授权成功与否,都能完成请求体缓存
  • 优先用官方工厂实现,避免手动写缓存逻辑

优雅解决方案

别把缓存逻辑包装成自定义WebFilter,直接把CacheRequestBodyGatewayFilterFactory注册为全局过滤器,并指定执行顺序在Spring Security过滤器之前。

实现代码

@Configuration
public class GatewayGlobalFilterConfig {

    @Bean
    public GlobalFilter requestBodyCachingGlobalFilter(CacheRequestBodyGatewayFilterFactory cacheRequestBodyFactory) {
        // 配置缓存参数,这里以缓存为DataBuffer为例,可按需调整
        CacheRequestBodyGatewayFilterFactory.Config config = new CacheRequestBodyGatewayFilterFactory.Config();
        config.setBodyClass(DataBuffer.class);
        
        GatewayFilter cacheFilter = cacheRequestBodyFactory.apply(config);
        
        // 调用官方过滤器逻辑
        return (exchange, chain) -> cacheFilter.filter(exchange, chain);
    }

    // 注册全局过滤器并设置优先级,确保在Spring Security第一个过滤器之前执行
    @Bean
    public FilterRegistrationBean<GlobalFilter> requestBodyCachingFilterRegistration(GlobalFilter requestBodyCachingGlobalFilter) {
        FilterRegistrationBean<GlobalFilter> registration = new FilterRegistrationBean<>(requestBodyCachingGlobalFilter);
        // SecurityWebFiltersOrder.FIRST的顺序值是0,设为-1保证优先级更高
        registration.setOrder(SecurityWebFiltersOrder.FIRST.getOrder() - 1);
        return registration;
    }
}

关键说明

  • 全局过滤器对所有请求生效,通过FilterRegistrationBean可以精确控制执行顺序,确保在Spring Security所有过滤器之前运行
  • 直接复用官方工厂的缓存逻辑,避免手动处理请求体缓存的细节(比如数据流释放、重复读取等坑)
  • 缓存后的请求体可以通过ServerWebExchangeUtils.CACHED_REQUEST_BODY_ATTR属性获取,后续安全过滤器或日志组件都能直接读取

补充说明

如果只需要针对特定路由配置缓存,也可以在路由定义中指定过滤器顺序,但全局过滤器的方式更通用,能覆盖所有请求场景,更推荐使用。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.12 10:43:16