首页 > 解决方案 > spring security 如何为不同的请求路径设置不同的过滤器?

问题描述

我有两个过滤器,我想将一个应用于“/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();
    }

更新:

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

标签: springspring-bootspring-security

解决方案


以下是定义应用过滤器的 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;
    }

}

通过这种方式,您还应该通过调用 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();
    }

}

配置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();
    }

}

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


推荐阅读