如何在Spring Security上针对不同的请求路径使用不同的过滤器?

Thi*_*yão 2 spring spring-security spring-boot

我有两个过滤器,我想对“/relatorios/**”应用一个,对其余的应用另一个。

怎么做?

这是我的(不起作用)版本:

    @Override
    protected void configure(HttpSecurity httpSecurity) throws Exception {
        httpSecurity.antMatcher("/relatorios/**")
                    .csrf()
                    .disable()
                    .sessionManagement()
                    .sessionCreationPolicy(SessionCreationPolicy.STATELESS)
                    .and()
                    .addFilter(relatoriosFilter)
                    .addFilterBefore(new ExceptionTranslationFilter(new Http403ForbiddenEntryPoint()),
                                     relatoriosFilter.getClass())
                    .authorizeRequests()
                    .and()
                    .antMatcher("/**")
                    .csrf()
                    .disable()
                    .sessionManagement()
                    .sessionCreationPolicy(SessionCreationPolicy.STATELESS)
                    .and()
                    .addFilter(authHeaderTokenFilter)
                    .addFilterBefore(new ExceptionTranslationFilter(new Http403ForbiddenEntryPoint()),
                                     authHeaderTokenFilter.getClass())
                    .authorizeRequests()
                    .anyRequest()
                    .authenticated();
    }
Run Code Online (Sandbox Code Playgroud)

更新:

在这个版本中,当我调用任何请求路径时,两个过滤器都会被调用。我希望“/relatorios/**”调用一个过滤器,而其他所有内容都调用另一个过滤器。

Yon*_*kof 9

以下是定义应用过滤器的 URL 路径的两种方法。

首先,您应该知道,创建实现 Filter 接口的过滤器类的 bean,然后过滤器会自动注册到所有端点。由于您正在尝试为不同的路径实现不同的过滤器,因此如果您在代码中这样做,请删除它。

现在您可以通过以下两种方法之一注册您的过滤器。

方法 1 - 使用 FilterRegistrationBean 注册过滤器

在此方法中,您定义的安全链不应定义您的客户过滤器,因此请从其中删除两个 addFilter 方法。您将不通过链设置路径,而是通过注册 bean 设置路径。

@Configuration
public class FilterConfiguration {

    @Bean
    public FilterRegistrationBean<RelatoriosFilter> relatoriosFilter(){
        FilterRegistrationBean<RelatoriosFilter> registrationBean
                = new FilterRegistrationBean<>();

        registrationBean.setFilter(new RelatoriosFilter());
        registrationBean.addUrlPattern("/relatorios/*");
        registrationBean.setOrder(ORDERED.HIGHEST_PRECEDENCE);

        return registrationBean;
    }

    @Bean
    public FilterRegistrationBean<AuthHeaderTokenFilter> filter2(){
        FilterRegistrationBean<AuthHeaderTokenFilter> registrationBean
                = new FilterRegistrationBean<>();

        registrationBean.setFilter(new AuthHeaderTokenFilter());
        registrationBean.addUrlPattern("/*");
        registrationBean.setOrder(ORDERED.HIGHEST_PRECEDENCE);


        return registrationBean;
    }

}
Run Code Online (Sandbox Code Playgroud)

通过这种方式,您还应该通过调用 setOrder 方法来控制过滤器的顺序,并为过滤链中的较高优先级提供较低的数字。必要的顺序取决于您正在使用的 Spring 版本以及您有兴趣在链中注入链的哪个部分。在我的示例中,它将是第一个过滤器。


方法 2 - 拆分 WebSecurityConfigurerAdapter 配置

WebSecurityConfigurerAdapter 链无法通过路径匹配来定义两个不同的过滤器配置。这是该链的各种限制之一。

通过创建附加配置可以轻松解决此问题,以便每个配置匹配不同的路径并应用不同的过滤器。您最终将得到两种配置。

配置1

@Configuration
@Order(1)
public class RelatoriosSecurity extends WebSecurityConfigurerAdapter {


    @Override
    protected void configure(HttpSecurity httpSecurity) throws Exception {
        httpSecurity
                .authorizeRequests()
                .and()
                .antMatcher("/relatorios/**")
                .addFilterBefore(new RelatoriosFilter(), ChannelProcessingFilter.class)
                .sessionManagement()
                .sessionCreationPolicy(SessionCreationPolicy.STATELESS)
                .and()
                .authorizeRequests().anyRequest().authenticated();
    }

}
Run Code Online (Sandbox Code Playgroud)

配置2

@Configuration
@Order(2)
public class GeneralSecurity extends WebSecurityConfigurerAdapter {

    @Override
    protected void configure(HttpSecurity httpSecurity) throws Exception {
        httpSecurity
                .antMatcher("/**")
                .sessionManagement()
                .sessionCreationPolicy(SessionCreationPolicy.STATELESS)
                .and()
                .addFilterBefore(new AuthHeaderTokenFilter(), ChannelProcessingFilter.class)
                .authorizeRequests().anyRequest().authenticated();
    }

}
Run Code Online (Sandbox Code Playgroud)

在此方法中,@Order 注释定义了链的执行顺序,与您的原始解决方案非常相似,RelatoriosSecurity 链将在 GeneralSecurity 链之前执行。另外,addFilterBefore 将定义提供的过滤器将在哪个过滤器之前运行。之前的过滤器的类取决于您的 Spring 版本,但在我的 ChannelProcessingFilter 中是第一个,因此我们提供的过滤器将在 ChannelProcessingFilter 之前首先执行。

  • 如何使用当前的 Spring security 5.7.0+ 来做到这一点? (3认同)