I want to have two different http web configurations with custom authentication filters using spring boot and spring java config. I followed the sample application that can be found here: https://github.com/spring-projects/spring-security-javaconfig/blob/master/samples-web.md#sample-multi-http-web-configuration. My understanding was, that this would end up in a separate spring filter chain for each of the web configurations. But both filters are invoked although the web configuration url pattern doesn't match the request. For instance, requesting http://localhost:8080/api/dosomething will invoke both filters, not only CustomApiAuthenticationFilter. Of course, it would be possible to check the request url in doFilterInternal and ignore the request if it doesn't match but I thought this should be done automatically by respecting the url pattern of the corresponding web configuration. Furthermore, my RestController doesn't get called respectively Postman only receives Status Code 200 OK with no response body.
Two questions: 1. Is this behaviour by design or is the configuration wrong? 2. Why is my RestController not invoked?
@EnableWebSecurity
public class SecurityConfiguration {
@Configuration
@Order(1)
public static class ApiConfigurationAdapter extends WebSecurityConfigurerAdapter {
@Bean
public GenericFilterBean apiAuthenticationFilter() {
return new CustomApiAuthenticationFilter();
}
@Override
protected void configure(HttpSecurity http) throws Exception {
http.antMatcher("/api/**").addFilterAfter(apiAuthenticationFilter(), AbstractPreAuthenticatedProcessingFilter.class)
.sessionManagement().sessionCreationPolicy(SessionCreationPolicy.STATELESS)
.and()
.authorizeRequests().antMatchers("/api/**").authenticated();
}
}
@Configuration
@Order(2)
public static class WebSecurityConfiguration extends WebSecurityConfigurerAdapter {
@Bean
public GenericFilterBean webAuthenticationFilter() {
return new CustomWebAuthenticationFilter();
}
@Override
protected void configure(HttpSecurity http) throws Exception {
http.antMatcher("/").addFilterAfter(webAuthenticationFilter(), AbstractPreAuthenticatedProcessingFilter.class)
.authorizeRequests().antMatchers("/").authenticated();
}
}
}
public class CustomApiAuthenticationFilter extends OncePerRequestFilter {
@Override
protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain) throws ServletException, IOException {
Authentication auth = new UsernamePasswordAuthenticationToken("sub", "password", ImmutableList.of(new SimpleGrantedAuthority("API")));
SecurityContextHolder.getContext().setAuthentication(auth);
}
}
public class CustomWebAuthenticationFilter extends OncePerRequestFilter {
@Override
protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain) throws ServletException, IOException {
Authentication auth = new UsernamePasswordAuthenticationToken("sub", "password", ImmutableList.of(new SimpleGrantedAuthority("USER")));
SecurityContextHolder.getContext().setAuthentication(auth);
}
}
@RestController
public class ApiController {
@RequestMapping(value = "/api/v1/dosomething", method = RequestMethod.GET)
public String getSomething() {
return "something";
}
}
Thanks to M. Deinum who gave me the right answer. The following now works as expected but still I'm not sure if this is a legitimate approach.
@EnableWebSecurity
public class SecurityConfiguration {
@Configuration
@Order(1)
public static class ApiConfigurationAdapter extends WebSecurityConfigurerAdapter {
@Override
protected void configure(HttpSecurity http) throws Exception {
http.antMatcher("/api/**")
.addFilterAfter(new CustomApiAuthenticationFilter(), AbstractPreAuthenticatedProcessingFilter.class)
.sessionManagement().sessionCreationPolicy(SessionCreationPolicy.STATELESS)
.and()
.authorizeRequests().anyRequest().hasRole("API");
}
}
@Configuration
@Order(2)
public static class WebSecurityConfiguration extends WebSecurityConfigurerAdapter {
@Override
protected void configure(HttpSecurity http) throws Exception {
http.antMatcher("/")
.addFilterAfter(new CustomWebAuthenticationFilter(), AbstractPreAuthenticatedProcessingFilter.class)
.authorizeRequests().anyRequest().hasRole("USER");
}
}
}
public class CustomApiAuthenticationFilter extends OncePerRequestFilter {
@Override
protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain) throws ServletException, IOException {
Authentication auth = new UsernamePasswordAuthenticationToken("sub", "password", ImmutableList.of(new SimpleGrantedAuthority("ROLE_API")));
SecurityContextHolder.getContext().setAuthentication(auth);
filterChain.doFilter(request, response);
}
}
public class CustomWebAuthenticationFilter extends OncePerRequestFilter {
@Override
protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain) throws ServletException, IOException {
Authentication auth = new UsernamePasswordAuthenticationToken("sub", "password", ImmutableList.of(new SimpleGrantedAuthority("ROLE_USER")));
SecurityContextHolder.getContext().setAuthentication(auth);
filterChain.doFilter(request, response);
}
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With