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?
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;
}