Home > Mobile >  How to configure Spring-Security (Spring 6) for not having Filters executed on unsecured routes?
How to configure Spring-Security (Spring 6) for not having Filters executed on unsecured routes?

Time:01-09

somewhat related to this other stackoverflow topic which doesn't give a proper solution nor is applicable to Spring 6 (Spring Boot 3).

I came up with a basic spring-boot app to make my case.

There is a controller with two end-points, where one must be secured and the other accessible.

@RestController
public class TestController {

    @GetMapping("/secured-api")
    public String securedApi() {
        return "secured";
    }

    @GetMapping("/public/open-api")
    public String openApi() {
        return "open";
    }

}

Security context as follow, imagine that MyFilter is doing something fancy, e.g: validating a JWT token and firing an exception if the token is invalid / expired.

@Configuration
public class ComponentSecurityContext {

    @Bean
    public SecurityFilterChain filterChain(HttpSecurity http) throws Exception {

        return http
            .addFilterAt(new MyFilter(), BasicAuthenticationFilter.class)
            .authorizeHttpRequests(customizer -> customizer
                .requestMatchers(new AntPathRequestMatcher("/public/**"))
                .permitAll()
                .anyRequest()
                .authenticated())
            .build();
    }

    public static class MyFilter extends OncePerRequestFilter {

        @Override
        protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response,
            FilterChain filterChain) throws ServletException, IOException {

            System.out.println("Filter is called for uri: "   request.getRequestURI());

            // performs some authentication

            filterChain.doFilter(request, response);
        }
    }

}

Executing the following two curls on the server

curl http://localhost:9003/public/open-api
curl http://localhost:9003/secured-api

is triggering MyFilter

Filter is called for uri: /public/open-api
Filter is called for uri: /secured-api

I would expect MyFilter to be called only for secured end-points, I don't care if an expired token is used to access an unprotected end-point.

Any advise on how to properly wire spring-security to achieve just that?

CodePudding user response:

Working solution where the filter is scoped by the securityMatcher:

@Bean
public SecurityFilterChain filterChain(HttpSecurity http) throws Exception {

    return http
        .securityMatcher(new NegatedRequestMatcher(new AntPathRequestMatcher("/public/**")))
        .addFilterAt(new MyFilter(), BasicAuthenticationFilter.class)
        .authorizeHttpRequests((requests) -> requests.anyRequest().authenticated())
        .build();
}
  • Related