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

如何确保SecurityFilterChain中的安全过滤器先于ProfileSynchronizationFilter执行?

问题:调整Spring Security认证过滤器与自定义过滤器的执行顺序

我有一个通过SecurityFilterChain注册的BearerTokenAuthenticationFilter(对应代码中的jwtAuthenticationFilter),另外还有一个通过FilterRegistrationBean注册的ProfileSynchronizationFilter。目前ProfileSynchronizationFilter会先于BearerTokenAuthenticationFilter执行,但实际需求是让ProfileSynchronizationFilter在认证过滤器之后运行。

我了解到SecurityFilterChain中的过滤器由DelegatingFilterProxy代理执行,推测需要调整DelegatingFilterProxy与ProfileSynchronizationFilter的执行顺序,但不确定思路是否正确以及具体实现方式。

当前配置代码

SecurityFilterChain 配置

@Bean
@Order(2)
public SecurityFilterChain filterChain(HttpSecurity http) throws Exception {
  http.csrf()
    .disable()
    .sessionManagement()
    .sessionCreationPolicy(SessionCreationPolicy.STATELESS)
    .and()
    .requestMatchers()
    .antMatchers(listOfSecuredResources)
    .and()
    .authorizeRequests()
    .antMatchers(listOfSecuredResources)
    .fullyAuthenticated()
    .and()
    .exceptionHandling()
    .authenticationEntryPoint(authenticationEntryPoint)
    .accessDeniedHandler(accessDeniedHandler)
    .and()
    .addFilter(jwtAuthenticationFilter)
    .anonymous()
    .disable();

  return http.build();
}

ProfileSynchronizationFilter 配置

@Bean
public FilterRegistrationBean registerProfileSynchronizationFilter(ProfileSynchronizationFilter profileSynchronizationFilter) {
  FilterRegistrationBean reg = new FilterRegistrationBean(profileSynchronizationFilter);
  reg.setOrder(6);
  return reg;
}

解决方案

要实现BearerTokenAuthenticationFilter先执行,有两种可靠的实现方式:

方案一:将自定义过滤器加入SecurityFilterChain内部(推荐)

这种方式能精准控制过滤器在Security链中的位置,避免和Servlet容器的其他过滤器顺序冲突。

  1. 修改SecurityFilterChain配置,在认证过滤器之后添加ProfileSynchronizationFilter:
@Bean
@Order(2)
public SecurityFilterChain filterChain(HttpSecurity http, ProfileSynchronizationFilter profileSynchronizationFilter) throws Exception {
  http.csrf()
    .disable()
    .sessionManagement()
    .sessionCreationPolicy(SessionCreationPolicy.STATELESS)
    .and()
    .requestMatchers()
    .antMatchers(listOfSecuredResources)
    .and()
    .authorizeRequests()
    .antMatchers(listOfSecuredResources)
    .fullyAuthenticated()
    .and()
    .exceptionHandling()
    .authenticationEntryPoint(authenticationEntryPoint)
    .accessDeniedHandler(accessDeniedHandler)
    .and()
    .addFilter(jwtAuthenticationFilter)
    // 明确指定在BearerTokenAuthenticationFilter之后执行
    .addFilterAfter(profileSynchronizationFilter, BearerTokenAuthenticationFilter.class)
    .anonymous()
    .disable();

  return http.build();
}
  1. 删除原来的FilterRegistrationBean配置,避免过滤器被重复注册:
// 移除该Bean定义
// @Bean
// public FilterRegistrationBean registerProfileSynchronizationFilter(ProfileSynchronizationFilter profileSynchronizationFilter) {
//   FilterRegistrationBean reg = new FilterRegistrationBean(profileSynchronizationFilter);
//   reg.setOrder(6);
//   return reg;
// }

方案二:调整自定义过滤器的Order值

如果必须保留FilterRegistrationBean的注册方式,需要确保自定义过滤器的Order值大于Spring Security核心过滤器FilterChainProxy的Order值(默认是-100)。因为Servlet过滤器的Order值越小,执行优先级越高,所以设置更大的Order值就能让它在Security过滤器之后运行。

修改FilterRegistrationBean配置:

@Bean
public FilterRegistrationBean registerProfileSynchronizationFilter(ProfileSynchronizationFilter profileSynchronizationFilter) {
  FilterRegistrationBean reg = new FilterRegistrationBean(profileSynchronizationFilter);
  // 设置Order值大于-100,确保在Security过滤器之后执行
  reg.setOrder(0);
  // 可选:限制过滤器仅对需要认证的资源生效,和Security配置保持一致
  reg.addUrlPatterns(listOfSecuredResources.toArray(new String[0]));
  return reg;
}

注意:如果项目中修改了Spring Security的默认Filter Order(比如通过security.filter.order配置项),需要将自定义过滤器的Order值设置为比该配置值更大的数。


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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.18 19:07:33