5

In my spring boot project I've got the following definition of a SecurityFilterChain:

public SecurityFilterChain filterChain(HttpSecurity http) throws Exception {
  http

    // public routes
    .authorizeHttpRequests()
    .requestMatchers("/", "/favicon.ico", "/v3/api-docs*")
    .permitAll()
    .and()

    // enable security for the log-view
    .authorizeHttpRequests()
    .requestMatchers("/log")
    .hasAnyRole(ROLE_LOGVIEWER)
    .and()

    // enable security for the health check
    .authorizeHttpRequests()
    .requestMatchers("/manage/health")
    .hasAnyRole(ROLE_HEALTH)
    .and()

    // enable basic-auth and ROLE_USER for all other routes
    .authorizeHttpRequests()
    .anyRequest()
    .hasAnyRole(ROLE_USER)
    .and()
    .httpBasic();

  return http.build();
}

It's tested in several mockup tests and runs as expected in the production environment.

But after the migration from spring-boot 3.0.8 to 3.0.9, I've got the following error:

Factory method 'filterChain' threw exception with message: This method cannot decide whether these patterns are Spring MVC patterns or not. If this endpoint is a Spring MVC endpoint, please use requestMatchers(MvcRequestMatcher); otherwise, please use requestMatchers(AntPathRequestMatcher).

I tried to use a more specific requst matcher, but without success.

Any hints for me?

Thilo Schwarz
  • 640
  • 5
  • 24

2 Answers2

5

I ran into the same exception in a very basic configuration with Spring Security 6.1.2. I solved it with:

@Bean
public SecurityFilterChain securityFilterChain(HttpSecurity http) throws Exception {
    return http.
            authorizeHttpRequests(requests -> {
                    requests.requestMatchers(new AntPathRequestMatcher("/"), new AntPathRequestMatcher("/style.css")).permitAll();
                    requests.requestMatchers(new AntPathRequestMatcher("/secure/**")).hasAuthority("MyAuthority");
            }).

I'm not sure if this is the right way do to it but it does seem to work. Within Spring Security 6, AbstractRequestMatcherRegistry doesn't have a .antMatchers() method anymore. Again, not really sure if this is the best way and not completely sure why I would want an ant matcher vs an MVC endpoint matcher.

user2959589
  • 362
  • 1
  • 9
  • 23
  • 1
    There is a GitHub issue already created. So for more info, check: https://github.com/spring-projects/spring-security/issues/13568 – Jake_3H Jul 27 '23 at 12:49
  • @Jake_3H Thanx for the link, very helpful. – Thilo Schwarz Jul 27 '23 at 15:50
  • @Jake_3H : So what is the right answer on this within 3.1.2? Do we use AntPathMatcher or MvcRequestMatcher? This is very important because it's the security configuration, and I want to make sure I'm protecting the resources I think I'm protecting. – user2959589 Jul 27 '23 at 18:47
  • 1
    That mostly depends on the patterns u use and their use-case. I would say AntPathMatcher is the way to go if u have exactly specific route(s), that u want to configure (for example in our app, we require auth for everything but /health route, so I went with AntPathMatcher). Here is a nice link explaining their difference: https://stackoverflow.com/questions/50536292/difference-between-antmatcher-and-mvcmatcherv – Jake_3H Jul 28 '23 at 21:56
0

user2959589 answer shows me the right way, thanks!

http
    // public routes
    .authorizeHttpRequests()
    .requestMatchers(AntPathRequestMatcher.antMatcher("/"))
    .permitAll()
    .requestMatchers(AntPathRequestMatcher.antMatcher("/favicon.ico"))
    .permitAll()
    .requestMatchers(AntPathRequestMatcher.antMatcher("/v3/api-docs*"))
    .permitAll()
    .and()

    // enable security for the log-view
    .authorizeHttpRequests()
    .requestMatchers(AntPathRequestMatcher.antMatcher("/log"))
    .hasAnyRole(ROLE_LOGVIEWER)
    .and()

    // enable security for the health check
    .authorizeHttpRequests()
    .requestMatchers(AntPathRequestMatcher.antMatcher("/manage/health"))
    .hasAnyRole(ROLE_HEALTH)
    .and()

    // enable basic-auth and ROLE_USER for all other routes
    .authorizeHttpRequests()
    .anyRequest()
    .hasAnyRole(ROLE_USER)
    .and()
    .httpBasic();
Thilo Schwarz
  • 640
  • 5
  • 24