I have a SpringBoot application with spring security. We have two path one for actuators : /actuator/** and one for our specific apis : /api/v1/mail/**.
I would like to apply a filter (ApiKeyFilter) only when a request is issued to /api/v1/mail/something and not when /actuator/something is called!
My configuration looks like :
@EnableWebSecurity
@EnableGlobalMethodSecurity(prePostEnabled = true)
public class SecurityConfiguration extends WebSecurityConfigurerAdapter {
@Configuration
@Order(1)
public static class ActuatorsConfigurator extends WebSecurityConfigurerAdapter {
@Override
protected void configure(HttpSecurity http) throws Exception {
http.antMatcher("/actuator/**").authorizeRequests().anyRequest().permitAll();
}
}
@Configuration
@Order(2)
public static class ApiConfigurator extends WebSecurityConfigurerAdapter {
@Autowired
private ApiKeyFilter filter;
private static final RequestMatcher PRIVATE_URLS = new AntPathRequestMatcher("/api/v1/mails/**");
@Override
protected void configure(HttpSecurity http) throws Exception {
http.antMatcher("/api/**")
.exceptionHandling()
.defaultAuthenticationEntryPointFor(forbiddenEntryPoint(), PRIVATE_URLS)
.and()
.authorizeRequests()
.antMatchers("/api/vi/mails/**")
.authenticated()
.and()
.addFilterBefore(filter, UsernamePasswordAuthenticationFilter.class)
.csrf().disable().httpBasic().disable().formLogin().disable().logout().disable();
}
@Bean
AuthenticationEntryPoint forbiddenEntryPoint() {
return new HttpStatusEntryPoint(HttpStatus.FORBIDDEN);
}
}
}
With this code my filter (ApiKEyFilter) is invoked when calling /actuator/health and when calling /api/vi/mail/retrieve that's not what i expected!
ApiKeyFilter :
@Component
public class ApiKeyFilter extends GenericFilterBean {
private static final Logger LOGGER = LoggerFactory.getLogger(ApiKeyFilter.class);
private final String API_KEY = "ApiKey";
@Override
public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
final String authParam = ofNullable(((HttpServletRequest) servletRequest).getHeader(HttpHeaders.AUTHORIZATION)).orElse(servletRequest.getParameter(API_KEY));
final String token = ofNullable(authParam).map(value -> StringUtils.removeStart(value, API_KEY)).map(String::trim)
.orElseThrow(() -> new BadCredentialsException("Missing api key"));
LOGGER.debug(token);
filterChain.doFilter(servletRequest, servletResponse);
}
}