Spring Boot 安全性 - 两个不同的过滤器

Posted

技术标签:

【中文标题】Spring Boot 安全性 - 两个不同的过滤器【英文标题】:Spring boot security - two distinct filters 【发布时间】:2017-02-03 14:19:27 【问题描述】:

我正在尝试使用两个不同的过滤器配置 Spring Security。 我想要的是有一些将由一个过滤器处理的 URL,以及一些将由其他过滤器处理的 URL。 这是我想出的设置:

@Configuration
@EnableWebSecurity
@EnableGlobalMethodSecurity(securedEnabled = true,prePostEnabled=true)
public class SecurityConfigurationContext 

    @Order(1)
    @Configuration
    public static class ConfigurerAdapter1 extends WebSecurityConfigurerAdapter
        ...

        @Override
        protected void configure(final HttpSecurity http) throws Exception 
            // Handlers and entry points
            http.exceptionHandling()
                .authenticationEntryPoint(MyCustomAuthenticationEntryPoint);


            http.authorizeRequests()
                .antMatchers(HttpMethod.GET, "/filter1-urls/*").hasRole("USER");


            http.addFilterBefore(myCustomFilter1, ChannelProcessingFilter.class);

            http.csrf().disable();
            http.httpBasic()
                .and()
                .sessionManagement().sessionCreationPolicy(SessionCreationPolicy.STATELESS);
        

        @Override
        protected void configure(AuthenticationManagerBuilder auth) throws Exception 
            auth.userDetailsService(myCustomAuthenticationService)
                .passwordEncoder(new BCryptPasswordEncoder());
        
    

    @Order(2)
    @Configuration
    public static class ConfigurerAdapter2 extends WebSecurityConfigurerAdapter
        ...

        @Override
        protected void configure(final HttpSecurity http) throws Exception 
            // Handlers and entry points
            http.exceptionHandling()
                .authenticationEntryPoint(MyCustomAuthenticationEntryPoint);


            http.authorizeRequests()
                .antMatchers(HttpMethod.GET, "/filter2-urls/*").hasRole("SUPER_USER");


            http.addFilterBefore(myCustomFilter2, ChannelProcessingFilter.class);

            http.csrf().disable();
            http.httpBasic()
                .and()
                .sessionManagement().sessionCreationPolicy(SessionCreationPolicy.STATELESS);
        

        @Override
        protected void configure(AuthenticationManagerBuilder auth) throws Exception 
            auth.userDetailsService(myCustomAuthenticationService)
                .passwordEncoder(new BCryptPasswordEncoder());
        
    

过滤器看起来像这样:

过滤器1:

@Component
@Order(1)
public final class MyCustomFilter1 implements Filter

    public MyCustomFilter1() 
        super();
    

    @Override
    public final void doFilter(final ServletRequest req, final ServletResponse res, final FilterChain chain) throws IOException, ServletException 
        // logic for processing filter1-urls
    

过滤器2:

@Component
@Order(2)
public final class MyCustomFilter2 implements Filter

    public MyCustomFilter2() 
        super();
    

    @Override
    public final void doFilter(final ServletRequest req, final ServletResponse res, final FilterChain chain) throws IOException, ServletException 
        // logic for processing filter2-urls
    

问题在于,对于每个请求,这两个过滤器都在一个链中调用。我提出的任何请求,它首先通过一个过滤器,然后通过另一个,而不是只通过一个。

我该如何解决这个问题?

提前致谢。

【问题讨论】:

【参考方案1】:

你应该只有一个ConfigurerAdapter。您可以将其组合成一个配置:

http.exceptionHandling()
            .authenticationEntryPoint(MyCustomAuthenticationEntryPoint);
http
     .authorizeRequests()
     .antMatchers(HttpMethod.GET, "/filter1-urls/*").hasRole("USER")
     .antMatchers(HttpMethod.GET, "/filter2-urls/*").hasRole("SUPER_USER");
http.addFilterBefore(myCustomFilter, ChannelProcessingFilter.class);

将调用这两个过滤器,因为您设置了此类行为。你应该只留下一个过滤器来达到你想要的结果。

@Component
public final class MyCustomFilter implements Filter 

    public MyCustomFilter() 
        super();
    

    @Override
    public final void doFilter(final ServletRequest req, final ServletResponse res, final FilterChain chain) throws IOException, ServletException 
    // logic for processing filter2-urls and filter1-urls
    
 

无论如何,您的过滤器都会被链式调用。如果你想拆分你的过滤器,你应该在你的过滤器中添加if语句来过滤只需要的url(你可以从ServletRequest获取请求url

@Component
public final class MyCustomFilter2 implements Filter 

    public MyCustomFilter2() 
        super();
    

    @Override
    public final void doFilter(final ServletRequest req, final ServletResponse res, final FilterChain chain) throws IOException, ServletException 
        if (/*is filter2 urls*/) 
        // logic for processing filter2-urls
        
    
 

【讨论】:

嗯。谢谢。我会试一试,如果我成功了,请告诉你。

以上是关于Spring Boot 安全性 - 两个不同的过滤器的主要内容,如果未能解决你的问题,请参考以下文章

用于过滤两个子实体的 Spring Boot 规范

在 Spring Boot 安全性中,无法跳过登录 url 的 OncePerRequestFilter 过滤器(基本上是在初始登录期间获取 JWT 令牌)

Spring Boot 安全配置不起作用

如何在 Spring Boot 安全性中禁用 CORS

如何在 Spring Boot 安全性中禁用 CORS

Spring Security 具有不同用户详细信息的多个 HTTPSecurity 服务在 Spring Boot 中不起作用