Home > Software design >  Spring Boot 3 Security requestMatchers.permitAll not working
Spring Boot 3 Security requestMatchers.permitAll not working

Time:12-16

Below is the SecurityFilterChain bean created according to the new Spring Security 6 / Spring boot 3 documentation. However, requestMatchers -> AntPathRequestMatcher -> permitAll is not working. Every request is reaching OncePerRequestFilter. Please let me know if this is expected or if something is wrong.

Code:

@Configuration
@EnableWebSecurity
@RequiredArgsConstructor
@EnableMethodSecurity
public class WebSecurityConfig {
   List<String> publicApis = List.of("/generate/**", "validated/**");
   
   @Bean
   public SecurityFilterChain securityFilterChain(HttpSecurity http) throws Exception {
        http
                .cors()
                .configurationSource(corsConfigurationSource())
                .and()
                .csrf()
                .disable()
                .formLogin()
                .disable()
                .httpBasic()
                .disable()
                .exceptionHandling()
                .authenticationEntryPoint(restAuthenticationEntryPoint())
                .and()
                .authorizeHttpRequests(
                        r -> r.requestMatchers(
                                        publicApis().stream()
                                                .map(AntPathRequestMatcher::new)
                                                .toArray(RequestMatcher[]::new)
                                )
                                .permitAll()
                                .anyRequest()
                                .authenticated()
                )
                .sessionManagement(s -> s.sessionCreationPolicy(SessionCreationPolicy.STATELESS))
                .addFilterBefore(tokenAuthenticationFilter, UsernamePasswordAuthenticationFilter.class);

        return http.build();
    }

    @Bean
    public WebSecurityCustomizer webSecurityCustomizer() {
        return (web) -> web.ignoring().requestMatchers(publicApis.toArray(String[]::new));
    }
}

SecurityFilter class:

@Component
@Slf4j
@RequiredArgsConstructor
public class SecurityFilter extends OncePerRequestFilter {

@Override
    protected void doFilterInternal(@NonNull HttpServletRequest request, @NonNull HttpServletResponse response, FilterChain filterChain) throws ServletException, IOException {
 log.info("request:{}", request); // all requests are logging including `/generate/a` or `/validate/1`
}

}

Ideally /generate/a or /validate/1 should not go to SecurityFilter. Still, there are going for JWT validation. How to avoid public APIs to bypass SecurityFilter.

Thanks in Advance.

CodePudding user response:

Your SecurityFilter is a @Component, therefore the filter will be picked up by Spring Boot and added to the filter chain.

Note that the filter chain that I mentioned is not the same chain as Spring Security, which is the SecurityFilterChain. Spring Security will not invoke the SecurityFilterChain for the endpoints you mentioned, because you did:

@Bean
public WebSecurityCustomizer webSecurityCustomizer() {
    return (web) -> web.ignoring().requestMatchers(publicApis.toArray(String[]::new));
}

I believe that since you are ignoring those endpoints, you do not need to permitAll them (those are different things).

One way to solve this is by adding the SecurityFilter to the SecurityFilterChain (which is not invoked for those endpoints):

  1. Remove @Component from your SecurityFilter
  2. Do http.addFilter(Before/After/At)(new SecurityFilter(), BeforeFilter.class)
  • Related