Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Spring Custom Filter is always invoked

I have a custom filter which is called before BasicAuthenticationFilter, the Bean is autowired in the SecurityConfig file.

.addFilterBefore(preAuthTenantContextInitializerFilter, BasicAuthenticationFilter.class)

Here is how the filter looks like.

@Component
public class PreAuthTenantContextInitializerFilter extends OncePerRequestFilter {
    @Autowired
    private TenantService tenantService;
.....
.....

I want this filter to not fire just like the rest of the Spring Security filter chain for paths included in WebSecurityConfigurerAdapter#configure(WebSecurity web) web.ignoring().

Here is how it looks like

@Configuration
public class WebSecurityConfig extends WebSecurityConfigurerAdapter {
    @Override
    public void configure(WebSecurity web) throws Exception {
        web.ignoring().antMatchers("/v2/api-docs", "/configuration/ui", "/swagger-resources", 
                                    "/configuration/security", "/swagger-ui.html", 
                                    "/webjars/**","/swagger-resources/configuration/ui",
                                    "/swagge‌​r-ui.html", "/docs/**");
    }
}

What I have already tried.

Remove the @Component annotation from the filter class, it only prevented the filter from invoking in any case since the filter is no more picked as a bean and will never make it to the filter chain.

What I am looking for

I want this filter to be called when the rest of the Spring Security chain is called and be ignored for the paths in web.ignoring() just like the rest of the Spring Security filters. Thanks.

like image 283
Adil Khalil Avatar asked Oct 05 '17 22:10

Adil Khalil


2 Answers

Any Servlet, Filter or Servlet *Listener instance that is a Spring bean will be registered with the embedded container. This can be particularly convenient if you want to refer to a value from your application.properties during configuration.

This snippet comes from the Spring Boot reference guide. Basically any Filter detected in the application context will be registered to the default filter chain and mapped to the DispatcherServlet or / .

In your case, as the filter is marked as @Component it will be a bean, Spring Boot detects is and registers it with the embedded container. However you don't want that as you want it to, only, be part of the Spring Security filter chain.

To do so you have 2 options.

  1. Remove the @Component and @Autowired and construct your own instance and don't make it a bean.
  2. Add an additional [FilterRegistrationBean] and set the enabled property to false, this will prevent Spring Boot from registering it with the embedded container.

Herer is the solution for option 2:

@Bean
public FilterRegistrationBean preAuthTenantContextInitializerFilterRegistration(PreAuthTenantContextInitializerFilter filter) {
    FilterRegistrationBean registration = new FilterRegistrationBean(filter);
    registration.setEnabled(false);
    return registration;
}

With this added bean Spring Boot will not register the filter with the embedded container and as such it will only be invoked as part of your Spring Security filter chain.

like image 141
M. Deinum Avatar answered Oct 21 '22 02:10

M. Deinum


  • I presume you are trying to ignore security for loading the Swagger UI page. If that's the case you need to add another path, /swagger-resources/configuration/security, to your list of ignored paths. Once you add this path, your PreAuthTenantContextInitializerFilter will not be invoked when you call any of the ignored paths.
  • Also, manage the creation of the PreAuthTenantContextInitializerFilter manually instead of having Spring managed. It will involve removing @Component from your filter. You can find a working example here.

    @Configuration
    public class WebSecurityConfig extends WebSecurityConfigurerAdapter {
       private TenantService service;
    
       @Autowired
       public SecurityConfiguration(TenantService service) {
           this.service = service;
       }
    
       @Override
       protected void configure(HttpSecurity http) throws Exception {
           http.addFilterBefore(
               new PreAuthTenantContextInitializerFilter(service),
               BasicAuthenticationFilter.class);
           ...
       }
    
       @Override
       public void configure(WebSecurity web) throws Exception {
           web.ignoring().antMatchers("/v2/api-docs", 
                "/configuration/ui",
                "/swagger-resources",
                "/configuration/security", "/swagger-ui.html",
                "/webjars/**", "/swagger-resources/configuration/ui",
                "/swagge‌r-ui.html", "/docs/**",
                "/swagger-resources/configuration/security");
       }
    }
    
like image 45
Indra Basak Avatar answered Oct 21 '22 04:10

Indra Basak