7

I have a custom Spring Security filter extending GenericFilterBean.

To do automatic dependency and bean creation I added a @Component annotation.

In my Security config I also register the filter like:

@Autowired
private RestAuthenticationFilter restAuthenticationFilter;

protected void configure(HttpSecurity http) throws Exception {
    // @formatter:off
    http
        .addFilterBefore(restAuthenticationFilter, LogoutFilter.class)

Everything works well except that my filter is called twice... It seems Spring adds filters also automatically to standard filters.

What should be the best approach here?

UPDATE

@Dave is this what you mean? It seems to work.

@Configuration
@ComponentScan
@EnableAutoConfiguration
public class Application extends WebMvcConfigurerAdapter {

    @Autowired
    private RestAuthenticationFilter restAuthenticationFilter;

    public static void main(String[] args) {
        SpringApplication.run(Application.class, args);
    }

    @Bean
    public ApplicationSecurity applicationSecurity() {
        return new ApplicationSecurity();
    }

    @Bean
    public FilterRegistrationBean filterRegistrationBean() {
        FilterRegistrationBean filterRegistrationBean = new FilterRegistrationBean();
        filterRegistrationBean.setEnabled(false);
        filterRegistrationBean.setFilter(restAuthenticationFilter);
        return filterRegistrationBean;
    }

    @Order(SecurityProperties.ACCESS_OVERRIDE_ORDER)
    protected static class ApplicationSecurity extends WebSecurityConfigurerAdapter {

        @Autowired
        private RestAuthenticationFilter restAuthenticationFilter;

        @Override
        protected void configure(HttpSecurity http) throws Exception {
            // @formatter:off
            http
                .addFilterBefore(restAuthenticationFilter, LogoutFilter.class)
                .authorizeRequests()
                    .anyRequest().authenticated()
                    .and()
                .csrf()
                    .disable()
                .exceptionHandling()
                    .authenticationEntryPoint(new Http403ForbiddenEntryPoint())
                    .and()
                .requestCache()
                    .requestCache(new NullRequestCache())
                    .and()
                .sessionManagement()
                    .sessionCreationPolicy(SessionCreationPolicy.STATELESS);
            // @formatter:on
        }
    }
}
Marcel Overdijk
  • 11,041
  • 17
  • 71
  • 110
  • Yes, that's what I meant. – Dave Syer Jun 24 '14 at 17:34
  • 1
    Thanks for confirming. It somehow feels nasty to explicitly disable the filter by declaring a FilterRegistrationBean @bean. – Marcel Overdijk Jun 25 '14 at 06:47
  • I think ideally a Filter's intent might be able to be inferred from a marker annotation (`@SecurityFilter`?) in conjunction with the `@Component` - ie - use me in the Security chain vs. use me in the standard filter chain. I ran into a similar issue myself, because my filter didn't need any Bean resources I did not register it as a `@Bean`, just a security Filter programmatically. – hoserdude Jun 26 '14 at 13:55
  • 1
    A @SecurityFilter annotations sounds great! What do you think Dave? File a github issue? – Marcel Overdijk Jun 26 '14 at 17:19

1 Answers1

8

You need to explicitly register the filter and mark it as "enabled=false" using the FilterRegistrationBean API. Then Spring Security will use it in its chain, but Boot will not try and register it as well.

Dave Syer
  • 56,583
  • 10
  • 155
  • 143
  • Thanks Dave, I'm trying to understand the answer... What you are basically saying is that Spring Boot is automatically adding the filter, and that I should register it as enabled=false to disable this behavior? I looked at FilterRegistrationBean apidocs but do not understand how to use enabled=false. Do yo maybe have some pointers or maube know some example? – Marcel Overdijk Jun 24 '14 at 14:27
  • I just noticed the RegistrationBean.setEnabled, I will try this. – Marcel Overdijk Jun 24 '14 at 14:30
  • Dave, see my updated question with code how I solved it. Is this the approach you meant? On a side note, wouldn't it be easier to have application.property to disable auto registering servlets and filters? In most cases you don't add ny any custom servlets; mainly the Spring Dispatcher servlet and security filters. – Marcel Overdijk Jun 24 '14 at 17:24
  • Programming in properties files again? The dispatcher servlet and the security filter are the same as any other servlet and filters as far as the `ApplicationContext` is concerned, so I don't think an environment setting is really appropriate in this case. – Dave Syer Jun 24 '14 at 17:37
  • The problem that I'm facing now with `setEnabled(false)` is that the `init` method for my custom filter is never called. How can I prevent the filter from being eagerly registered by Spring but still able to initialize when inserted in a spring security filter chain? – Tiago Feb 23 '22 at 18:57