如何确保在SecurityFilterChain中的安全过滤器之后执行过滤器?

问题描述 投票:0回答:1

我有一个

BearerTokenAuthenticationFilter
,它是通过
SecurityFilterChain
注册的。此外,还有一个通过
ProfileSynchronizationFilter
注册的
FilterRegistrationBean

BearerTokenAuthenticationFilter
需要在
ProfileSynchronizationFilter
之前执行。现在却发生相反的情况。

我的理解是

SecurityFilterChain
中的过滤器是由
DelegatingFilterProxy
执行的。所以,我认为
DelegatingFilterProxy
必须相对于
ProfileSynchronizationFilter
进行排序。但是,我不确定这是否是正确的方法 - 甚至不确定如何做到这一点。

摘自 Spring 文档:

enter image description here

https://docs.spring.io/spring-security/reference/servlet/architecture.html#servlet-filterchainproxy

如何解决此排序问题,以便

BearerTokenAuthenticationFilter
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;
}
spring-security servlet-filters
1个回答
0
投票

原帖中发布的插图很好地概述了过滤器和安全过滤器。 Spring 将

DelegatingFilterProxy
(springSecurityFilterChain) 安装为过滤器。正如类名所示,此过滤器将过滤委托给安全过滤器。

安全过滤器不能相对于常规过滤器进行订购。安全过滤器只能相对于其他安全过滤器进行订购。

要了解 Spring Boot 项目中的常规过滤器和安全过滤器,您可以使用下面的类,它将在应用程序启动时列出所有过滤器。

根据此列表,我能够解决过滤器排序问题。

对于我在原始帖子中描述的具体问题,执行顺序不可预测的原因之一是安全过滤器暴露为

Bean
。因此,Spring 安装了安全过滤器,既作为常规过滤器,又作为安全过滤器:

Springboot - 自动注册过滤器

@Component
public class FilterPrinter implements CommandLineRunner {

        @Autowired
        List<SecurityFilterChain> securityFilterChains;

        @Override
        public void run(String... args) throws Exception {
                for (int i = 0; i < securityFilterChains.size(); i++) {
                        SecurityFilterChain securityFilterChain = securityFilterChains.get(i);
                        System.out.println("security chain #" + (i + 1) + " filters:");
                        System.out.println("-----");
                        List<Filter> filters = securityFilterChain.getFilters();
                        filters.forEach(filter
                            -> System.out.println("- " + filter.getClass().getSimpleName())
                        );
                }

        }

        @Bean
        public CommandLineRunner cmdLineRunner(ApplicationContext context) {
                return args -> {
                        ServletContextInitializerBeans scib = new ServletContextInitializerBeans(context,
                            FilterRegistrationBean.class, DelegatingFilterProxyRegistrationBean.class);
                        System.out.println("request filters:");
                        System.out.println("----");
                        scib.iterator().forEachRemaining(s -> {
                                System.out.println("- " + s);
                        });
                };
        }

}
© www.soinside.com 2019 - 2024. All rights reserved.