11

I want to use @Autowire with a Filter. So I define my filter in the SecurityConfig as below:

    @Override
    protected void configure(HttpSecurity http) throws Exception {
        http.sessionManagement().sessionCreationPolicy(SessionCreationPolicy.STATELESS);
        http.addFilterBefore(getA(), BasicAuthenticationFilter.class);
        http.csrf().disable();
    }

    @Bean
    public A getA(){
        return new A();
    }

This filter A extends Spring's GenericFilterBean.

I get below output when I invoke the controller, which shows the filter hits twice.

filter A before
filter A before
mycontroller invoke
filter A after
filter A after

My observation is, this extra invocation invoke with Spring container because if filter is not register as bean, it only get hits once. What is the reason and how can I fix it?

dur
  • 15,689
  • 25
  • 79
  • 125
Harshana
  • 7,297
  • 25
  • 99
  • 173

3 Answers3

31

As you have observed, Spring Boot will automatically register any bean that is a Filter with the servlet container. One option is to not expose your Filter as a bean and only register it with Spring Security.

If you want to be able to autowire dependencies into your Filter then it has to be a bean. That means you need to tell Spring Boot not to register it as a Filter. As described in the documentation, you do that using a FilterRegistrationBean:

@Bean
public FilterRegistrationBean registration(MyFilter filter) {
    FilterRegistrationBean registration = new FilterRegistrationBean(filter);
    registration.setEnabled(false);
    return registration;
}
Andy Wilkinson
  • 108,729
  • 24
  • 257
  • 242
  • 8
    One invocation is by the servlet container and the other is by Spring Security – Andy Wilkinson Sep 05 '16 at 06:04
  • There's no separate container for Spring Security, but it has its own chain of filters that are used to decide whether or not a request should be permitted. – Andy Wilkinson Sep 13 '16 at 06:04
  • It's not a double-registration. By explicitly providing a `FilterRegistrationBean` for the filter that is disabled, you're preventing Spring Boot from creating one that is enabled. – Andy Wilkinson Jun 21 '17 at 19:12
  • Is there a way to prevent Spring from creating a duplicate filter while also specifying the filter order? We would like to specify setOrder for a filter that's also a bean. The automatically registered filter is being placed near the end of our filter chain regardless of what we do with our FilterRegistrationBean. – Alex Pritchard Oct 13 '17 at 18:27
  • 1
    @user1002065 And now how are you defining it? As @Bean? – inafalcao Jan 23 '22 at 16:33
1

If you are on Spring 6.0.2 or plus version and if using OncePerRequestFilter, Overriding shouldNotFilter method as follows will work.

    @Override
    protected boolean shouldNotFilter(HttpServletRequest request) {
        return request.getServletPath().contains("/api/path/which/needs/to/exclude");
    }
Hardik Patel
  • 1,033
  • 1
  • 12
  • 16
-1

Removing @Component from the filter class helped me.

public class AuthTokenFilter extends OncePerRequestFilter {

}
ahuemmer
  • 1,653
  • 9
  • 22
  • 29