Skip to content

Spring Boot HTTP security configuration anonymous filter and a custom filter on a different path

I have experienced a strange problem while trying to configure HTTP security by using WebSecurityConfigurerAdapter. Here is the full configuration class I tried so far:

@Slf4j
@Configuration
@EnableWebSecurity
@EnableGlobalMethodSecurity(securedEnabled = true)
@ConditionalOnProperty(name = "module.client.security.enabled")
public class SecurityConfig extends WebSecurityConfigurerAdapter {

  @Value("${management.endpoints.web.base-path}")
  private String managementEndpoint;

  @Autowired
  private List<ModuleProperties> moduleProperties;

  @Override
  public void configure(WebSecurity web) {
    web.ignoring()
        .antMatchers(this.managementEndpoint + "/**");
  }

  @Override
  protected void configure(HttpSecurity http) throws Exception {
    http.httpBasic().disable();
    http.formLogin().disable();
    // FIXME also doesn't work because of the later http.requestMatchers().antMatchers() calls
    http.authorizeRequests()
        .antMatchers("/**").anonymous();

    http.requestMatchers()
        .antMatchers("/app/**")
        .and()
        .addFilterBefore(new ClientResolveFilter(), FilterSecurityInterceptor.class);

  }

What I would like to do is actually enabling anonymous authentication for all endpoints — to prevent NullPointerExceptions when operating on SecurityContextHolder — Plus, enabling/adding a custom filter to only a subset or different endpoint path which is /app/** in this case.

I expected the above code would work but what exactly happens is the AnonymousAuthenticationFilter disabled for all and both filters only work for the path /app/** only.

If I remove the http.requestMatchers().antMatchers("/app/**") part, then AnonymousAuthenticationFilter works for all paths as normal. I suspect that the second .antMatchers("/app/**") call kinda replaces the former one or substitutes it implicitly which doesn’t make sense to me, but I could be wrong.

I tried diving into the source but still confused and cannot find a clean solution to make it work as my expectation. Any ideas and help will be appreciated.

Cheers!

EDIT: I’m using Spring Boot 2.5.2 and the Spring Security version is 5.5.1

Answer

After @Dickson’s advice, I found a special bean called FilterRegistrationBean provided by spring boot.

Thus, I configured it as a bean which applies a specific servlet filter to only configured paths:

@Bean
public FilterRegistrationBean<ClientResolveFilter> clientResolveFilter(){
  final FilterRegistrationBean<ClientResolveFilter> frb = new FilterRegistrationBean<>();
  frb.setFilter(new ClientResolveFilter());
  frb.addUrlPatterns("/app/*");
  return frb;
}

This solution worked perfectly for my requirement.

Pay attention to that the path string is not an ant matcher now — must be written with single /app/* instead of double /app/** — it’s actually the pattern when we manually configured web.xml file like in the old days 🙂