最新消息:雨落星辰是一个专注网站SEO优化、网站SEO诊断、搜索引擎研究、网络营销推广、网站策划运营及站长类的自媒体原创博客

java - Filter executing twice - Stack Overflow

programmeradmin7浏览0评论

here is the filter class. Using @Component annotation because I want to read the value auth.key from application.yml file.

@Component
public class StaticKeyAuthFilter implements Filter {

    @Value("${auth.key}")
    private String authKey;

    @Override
    public void doFilter(ServletRequest servletRequest,
                         ServletResponse servletResponse,
                         FilterChain filterChain) throws IOException, ServletException {
        HttpServletRequest request = (HttpServletRequest) servletRequest;
        HttpServletResponse response = (HttpServletResponse) servletResponse;

        String authorization = request.getHeader("Authorization");
        System.out.println("StaticKeyAuthFilter:" + request.getRequestURI() );

        if (authorization == null || !authorization.equals(authKey)) {
            response.setStatus(HttpServletResponse.SC_UNAUTHORIZED);
            return;
        }

        filterChain.doFilter(request, response);

    }
}

Next, I am registering it in the config class.

@Configuration
public class ProjectConfig {
    @Autowired
    private StaticKeyAuthFilter staticKeyAuthFilter;
    
    @Bean
    SecurityFilterChain configure(HttpSecurity httpSecurity) throws Exception {

        httpSecurity.authorizeHttpRequests(c -> {
            c.anyRequest().permitAll();
        });


        httpSecurity.addFilterAt(staticKeyAuthFilter, BasicAuthenticationFilter.class);
        return httpSecurity.build();
    }
}

Now, when I visit any controller I get the following output:

StaticKeyAuthFilter:/category/bb
StaticKeyAuthFilter:/category/bb

As you can see, it is executing twice. what am I doing wrong?

here is the filter class. Using @Component annotation because I want to read the value auth.key from application.yml file.

@Component
public class StaticKeyAuthFilter implements Filter {

    @Value("${auth.key}")
    private String authKey;

    @Override
    public void doFilter(ServletRequest servletRequest,
                         ServletResponse servletResponse,
                         FilterChain filterChain) throws IOException, ServletException {
        HttpServletRequest request = (HttpServletRequest) servletRequest;
        HttpServletResponse response = (HttpServletResponse) servletResponse;

        String authorization = request.getHeader("Authorization");
        System.out.println("StaticKeyAuthFilter:" + request.getRequestURI() );

        if (authorization == null || !authorization.equals(authKey)) {
            response.setStatus(HttpServletResponse.SC_UNAUTHORIZED);
            return;
        }

        filterChain.doFilter(request, response);

    }
}

Next, I am registering it in the config class.

@Configuration
public class ProjectConfig {
    @Autowired
    private StaticKeyAuthFilter staticKeyAuthFilter;
    
    @Bean
    SecurityFilterChain configure(HttpSecurity httpSecurity) throws Exception {

        httpSecurity.authorizeHttpRequests(c -> {
            c.anyRequest().permitAll();
        });


        httpSecurity.addFilterAt(staticKeyAuthFilter, BasicAuthenticationFilter.class);
        return httpSecurity.build();
    }
}

Now, when I visit any controller I get the following output:

StaticKeyAuthFilter:/category/bb
StaticKeyAuthFilter:/category/bb

As you can see, it is executing twice. what am I doing wrong?

Share Improve this question edited Mar 25 at 9:22 asgarov1 4,2262 gold badges10 silver badges25 bronze badges asked Mar 25 at 8:52 CodyCody 2,6516 gold badges33 silver badges65 bronze badges 3
  • 2 Instead of implementing Filter, you should try extending Spring's OncePerRequestFilter. This is also recommended by the Spring Docs. baeldung/spring-onceperrequestfilter – pebble unit Commented Mar 25 at 9:04
  • I did use OncePerRequestFilter its now executing only once. Can you please explain the reason behind this behaviour? – Cody Commented Mar 25 at 9:06
  • But my application is very simple and doesn't have multiple servelets – Cody Commented Mar 25 at 9:09
Add a comment  | 

1 Answer 1

Reset to default 4

As soon as you register a Filter bean as a component, it's already added to the regular filter chain. In addition, you manually added it to the SecurityFilterChain as well, which causes it to be registered and called twice.

Potential solutions:

  • You can extend from OncePerRequestFilter which guarantees that the filter is only invoked once no matter how many times it's registered within the filter chain. The downside is that it might run it as part of your regular filter chain and not your security filter chain.

  • You can remove the @Component annotation and manually create the filter, e.g:

    @Bean
    SecurityFilterChain configure(HttpSecurity httpSecurity, @Value("${auth.key}") String authKey) throws Exception {
    
        httpSecurity.authorizeHttpRequests(c -> {
            c.anyRequest().permitAll();
        });
    
    
        httpSecurity.addFilterAt(new StaticKeyAuthFilter(authKey), BasicAuthenticationFilter.class);
        return httpSecurity.build();
    }
    
  • You can define a FilterRegistrationBean to disable the filter from being automatically added to the filter chain (as suggested by M. Deinum) and so that it's only present in the security filter chain:

    @Bean
    public FilterRegistrationBean staticKeyAuth(StaticKeyAuthFilter filter) {
        FilterRegistrationBean registration = new FilterRegistrationBean(filter);
        registration.setEnabled(false);
        return registration;
    }
    
发布评论

评论列表(0)

  1. 暂无评论