When to use Spring Security`s antMatcher()?
Spring MvcSpring SecuritySpring Security4Spring Mvc Problem Overview
When do we use antMatcher()
vs antMatchers()
?
For example:
http
.antMatcher("/high_level_url_A/**")
.authorizeRequests()
.antMatchers("/high_level_url_A/sub_level_1").hasRole('USER')
.antMatchers("/high_level_url_A/sub_level_2").hasRole('USER2')
.somethingElse()
.anyRequest().authenticated()
.and()
.antMatcher("/high_level_url_B/**")
.authorizeRequests()
.antMatchers("/high_level_url_B/sub_level_1").permitAll()
.antMatchers("/high_level_url_B/sub_level_2").hasRole('USER3')
.somethingElse()
.anyRequest().authenticated()
.and()
...
What I expect here is,
- Any request matches to
/high_level_url_A/**
should be authenticated +/high_level_url_A/sub_level_1
only for USER and/high_level_url_A/sub_level_2
only for USER2 - Any request matches to
/high_level_url_B/**
should be authenticated +/high_level_url_B/sub_level_1
for public access and/high_level_url_A/sub_level_2
only for USER3. - Any other pattern I don't care - But should be public ?
I have seen latest examples do not include antMatcher()
these days. Why is that? Is antMatcher()
no longer required?
Spring Mvc Solutions
Solution 1 - Spring Mvc
You need antMatcher
for multiple HttpSecurity
, see Spring Security Reference:
> 5.7 Multiple HttpSecurity
>
> We can configure multiple HttpSecurity instances just as we can have multiple <http>
blocks. The key is to extend the WebSecurityConfigurationAdapter
multiple times. For example, the following is an example of having a different configuration for URL’s that start with /api/
.
>
> @EnableWebSecurity
> public class MultiHttpSecurityConfig {
> @Autowired
> public void configureGlobal(AuthenticationManagerBuilder auth) { 1
> auth
> .inMemoryAuthentication()
> .withUser("user").password("password").roles("USER").and()
> .withUser("admin").password("password").roles("USER", "ADMIN");
> }
>
> @Configuration
> @Order(1) 2
> public static class ApiWebSecurityConfigurationAdapter extends WebSecurityConfigurerAdapter {
> protected void configure(HttpSecurity http) throws Exception {
> http
> .antMatcher("/api/**") 3
> .authorizeRequests()
> .anyRequest().hasRole("ADMIN")
> .and()
> .httpBasic();
> }
> }
>
> @Configuration 4
> public static class FormLoginWebSecurityConfigurerAdapter extends WebSecurityConfigurerAdapter {
>
> @Override
> protected void configure(HttpSecurity http) throws Exception {
> http
> .authorizeRequests()
> .anyRequest().authenticated()
> .and()
> .formLogin();
> }
> }
> }
>
> 1 Configure Authentication as normal
>
> 2 Create an instance of WebSecurityConfigurerAdapter
that contains @Order
to specify which WebSecurityConfigurerAdapter
should be considered first.
>
> 3 The http.antMatcher
states that this HttpSecurity
will only be applicable to URLs that start with /api/
>
> 4 Create another instance of WebSecurityConfigurerAdapter
. If the URL does not start with /api/
this configuration will be used. This configuration is considered after ApiWebSecurityConfigurationAdapter
since it has an @Order
value after 1
(no @Order
defaults to last).
In your case you need no antMatcher
, because you have only one configuration. Your modified code:
http
.authorizeRequests()
.antMatchers("/high_level_url_A/sub_level_1").hasRole('USER')
.antMatchers("/high_level_url_A/sub_level_2").hasRole('USER2')
.somethingElse() // for /high_level_url_A/**
.antMatchers("/high_level_url_A/**").authenticated()
.antMatchers("/high_level_url_B/sub_level_1").permitAll()
.antMatchers("/high_level_url_B/sub_level_2").hasRole('USER3')
.somethingElse() // for /high_level_url_B/**
.antMatchers("/high_level_url_B/**").authenticated()
.anyRequest().permitAll()
Solution 2 - Spring Mvc
I'm updating my answer...
antMatcher()
is a method of HttpSecurity
, it doesn't have anything to do with authorizeRequests()
. Basically, http.antMatcher()
tells Spring to only configure HttpSecurity
if the path matches this pattern.
The authorizeRequests().antMatchers()
is then used to apply authorization to one or more paths you specify in antMatchers()
. Such as permitAll()
or hasRole('USER3')
. These only get applied if the first http.antMatcher()
is matched.
Solution 3 - Spring Mvc
Basically http.antMatcher()
tells Spring to only configure HttpSecurity
if the path matches this pattern.