如何在spring security上为不同的请求路径设置不同的过滤器?

qcbq4gxm  于 2023-08-05  发布在  Spring
关注(0)|答案(2)|浏览(210)

我有两个过滤器,我想在“/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/**”调用一个过滤器,其他所有内容调用另一个过滤器。

z2acfund

z2acfund1#

以下是定义应用过滤器的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将定义所提供的过滤器将在哪个过滤器之前运行。之前的filter的类将取决于您的Spring版本,但在我的版本中,ChannelProcessingFilter是第一个,因此我们提供的filter将首先执行,在ChannelProcessingFilter之前。

jucafojl

jucafojl2#

Yonathan的答案是正确的,但在Spring的新版本中,很多事情都发生了变化。WebSecurityConfigurerAdapter类从5.7.x开始被弃用,在Spring 6.0中不再可用。

此外,HttpSecurity类的整个构建器api集也发生了变化。例如:.antMatcher()不再可用。
为了使上述功能与最新版本的Spring/SpringBoot一起工作,您必须创建SecurityFilterChain类的多个Bean。
例如:

@Configuration
@EnableWebSecurity
public class SecurityConfig {

@Bean
@Order(1)
public SecurityFilterChain filterChain1(HttpSecurity httpSecurity) throws Exception {
    httpSecurity.csrf((csrf) -> csrf.disable()).securityMatcher("/relatorios/**")
            .sessionManagement(
                    sessionManagement -> sessionManagement.sessionCreationPolicy(SessionCreationPolicy.STATELESS))
            .authorizeHttpRequests((authorizeRequests) -> {
                authorizeRequests.anyRequest().authenticated();
            })
            .addFilterBefore(new RelatoriosFilter(), UsernamePasswordAuthenticationFilter.class)
            .formLogin(formLogin -> {
                formLogin.disable();
            }).exceptionHandling(exceptionHandling -> exceptionHandling.disable());
    return httpSecurity.build();
}

@Bean
@Order(2)
public SecurityFilterChain filterChain2(HttpSecurity httpSecurity) throws Exception {
    httpSecurity.csrf((csrf) -> csrf.disable()).securityMatcher("/**")
            .sessionManagement(
                    sessionManagement -> sessionManagement.sessionCreationPolicy(SessionCreationPolicy.STATELESS))
            .authorizeHttpRequests((authorizeRequests) -> {
                authorizeRequests.anyRequest().authenticated();
            })
            .addFilterBefore(new AuthHeaderTokenFilter(), UsernamePasswordAuthenticationFilter.class)
            .formLogin(formLogin -> {
                formLogin.disable();
            }).logout((logout) -> {
                logout.logoutUrl("/logout").permitAll();
            }).exceptionHandling(exceptionHandling -> exceptionHandling.disable());
    return httpSecurity.build();
    }

}

字符串

相关问题