15

Just want to see whether I'm interpreting the answer to this question the right way.

If we only need to secure one path like this:

http.antMatcher("/api/**").authorizeRequests()....

Then use antMatcher().

If we need to secure multiple URL paths like this:

http
.authorizeRequests()
    .antMatchers("/high_level_url_A/sub_level_1").hasRole('USER')
    .antMatchers("/high_level_url_A/sub_level_2").hasRole('USER2')
    ...

Then use antMatchers().

There are two answers in this question, but the example provided in each of them contradicts example given in the other. The first answer says that the author does not need antMatcher() and the second says to always start with `antMatcher() IIUC.

Ole
  • 41,793
  • 59
  • 191
  • 359

2 Answers2

22

HttpSecurity.antMatcher() changes the default request matcher for the HttpSecurity instance to an AntPathRequestMatcher from AnyRequestMatcher. ExpressionUrlAuthorizationConfigurer.ExpressionInterceptUrlRegistry.antMatchers() is used for applying authorization rules to a subset of endpoints associated with the current HttpSecurity instance.

Example code:

http
    .antMatcher("/api/**")
    .httpBasic()
        .disable()
    .authorizeRequests()
        .antMatchers("/api/user/**", "/api/ticket/**", "/index")
            .hasRole("USER");

In the example above, basic authorization is disabled for all endpoints matching /api/**. Additionally, endpoints matching /api/user/** or /api/ticket/** will require the request's Authentication to contain ROLE_USER. However, when a user attempts to access /index, they will be met with a basic auth prompt. Upon entering credentials, the user will be granted access to the endpoint regardless of whether or not the request's Authentication contains ROLE_USER. This is because .antMatcher("/api/**") is limiting the scope of the entire HttpSecurity instance to that specific AntMatcher.

The example below would ensure that the HttpSecurity's scope includes the three previous AntMatchers and nothing else:

http
    .requestMatchers()
        .antMatchers("/api/user/**", "/api/ticket/**", "/index")
        .and()
    .httpBasic()
        .disable()
    .authorizeRequests()
        .any()
            .hasRole("USER");

EDIT If you use #hasRole(), then your role should not start with "ROLE_" as this is automatically inserted.

dsep
  • 519
  • 4
  • 10
  • @Ole: No, you don't make global security settings, you make always settings for a configuration. You only configure which configuration is used with ` antMatcher()`. – dur Nov 17 '17 at 16:44
  • Just to make it clear, the result of your example would change if you don't use Spring Boot, because Spring Boot has default configurations. And to make your example work with Spring Boot, it is neccessary that the order of the configurations is right. – dur Nov 17 '17 at 16:47
  • So just to make sure I'm getting it if we do http.antMatcher("/api/**") then Spring creates a configuration for "/api/**" and then we proceed to apply specific configuration settings for that configuration? If we say http.antMatcher("v2/api/**") then Spring creates antother security configuration applicable to version 2 of the API? – Ole Nov 17 '17 at 21:01
  • 2
    @Ole calling antMatcher() twice on the same HttpSecurity instance will just replace the original antMatcher. To apply the same HttpSecurity configuration to multiple antMatchers, use http.requestMatchers(). antMatchers(). The alternative is to create multiple SecurityConfigurers with each using its own antMatcher and then annotating them with \@order to ensure that spring loads all of them. – dsep Nov 18 '17 at 01:03
  • Hello @dsep, I'm using Hybrid Configuration, I need to authorize two different paths in my JwtSecurityConfig. ex: /web/** and /mobile/**, how can I do that? https://stackoverflow.com/questions/58231064/spring-security-multihttpsecurity-configuration-so-that-i-can-perform-two-types – Shiva kumar Oct 23 '19 at 11:06
1

antMatcher() allows configuring the HttpSecurity to only be invoked when matching the provided ant pattern.

If more advanced configuration is necessary, consider using requestMatchers() or requestMatcher(RequestMatcher).

Invoking antMatcher() will override previous invocations of antMatcher(), mvcMatcher(), requestMatchers(), regexMatcher(), and requestMatcher()

See the example bellow for using requestMatchers

   @Configuration
   @EnableWebSecurity
   public class RequestMatchersSecurityConfig extends WebSecurityConfigurerAdapter {
  
    @Override
    protected void configure(HttpSecurity http) throws Exception {
        http
            .requestMatchers((requestMatchers) ->
                requestMatchers
                    .antMatchers("/api/**")
                    .antMatchers("/oauth/**")
            )
            .authorizeRequests((authorizeRequests) ->
                authorizeRequests
                    .antMatchers("/**").hasRole("USER")
            )
            .httpBasic(withDefaults());
    }
   }

The configuration below is also the same as the above configuration.

   @Configuration
   @EnableWebSecurity
   public class RequestMatchersSecurityConfig extends WebSecurityConfigurerAdapter {
  
    @Override
    protected void configure(HttpSecurity http) throws Exception {
        http
            .requestMatchers((requestMatchers) ->
                requestMatchers
                    .antMatchers("/api/**")
            )
            .requestMatchers((requestMatchers) ->
            requestMatchers
                .antMatchers("/oauth/**")
            )
            .authorizeRequests((authorizeRequests) ->
                authorizeRequests
                    .antMatchers("/**").hasRole("USER")
            )
            .httpBasic(withDefaults());
    }
   }
Charden Daxicen
  • 405
  • 5
  • 10