3

I'm learnig spring security and I came across this piece of code from https://spring.io/guides/tutorials/spring-boot-oauth2/

 @Override
  protected void configure(HttpSecurity http) throws Exception {
    http
      .antMatcher("/**")
      .authorizeRequests()
        .antMatchers("/", "/login**", "/webjars/**", "/error**")
        .permitAll()
      .anyRequest()
        .authenticated();
  }

I removed .antMatcher("/**") and the code is still working. I understand ** matches zero or more directories in a path, So I thought antMatcher("/**").authorizeRequestes().antMatcher("/login") would match "/login" that is directly or indirectly under root path, ie I expected it match paths like /login and /demo/login but that's not the case, It matches only /login that's directly underneath the root path. So what exactly is the need for .antMatcher("/**") here?

Ken Chan
  • 84,777
  • 26
  • 143
  • 172
Arjun
  • 1,116
  • 3
  • 24
  • 44

2 Answers2

6

They are difference things.

  • http.antMatcher() configures which URL will be handled by this SecurityFilterChain. The default is to match all URL. That why it is the same if you remove http.antMatcher("/**").

  • http.authorizeRequests() configures the authorisation matter for an URL such as things like if it requires to be authenticated or if only certain roles can access it etc.

So if an URL does not matched with http.antMatcher() , Spring security will not handle it and http.authorizeRequests() will not apply to this URL. In other words , in order to have the URL configured in http.authorizeRequests() to take effect , it should be handled by Spring Security and matched in http.antMatcher() too.

Ken Chan
  • 84,777
  • 26
  • 143
  • 172
4

Note that the first one is singular antMatcher and the second one is plural antMatchers, and that the example has them indented differently.

Actually, the example in the question is incorrectly indented. Correct indentation is:

@Override
protected void configure(HttpSecurity http) throws Exception {
  http
    .antMatcher("/**")
    .authorizeRequests()
      .antMatchers("/", "/login**", "/webjars/**", "/error**")
        .permitAll()
      .anyRequest()
        .authenticated();
}

That is because they apply to two entirely different objects:

  • The first call applies to the HttpSecurity object, and specifies a master filter, that is applied before even considering security.

    The default master filter is the AnyRequestMatcher, and the javadoc says:

    Matches any supplied request.

    When you call antMatcher("/**"), you replace that filter with an AntPathRequestMatcher using pattern /**, and the javadoc says:

    Using a pattern value of /** or ** is treated as a universal match, which will match any request.

    As you can see, calling antMatcher("/**") has no effect, other than explicitly documenting that security is applied to all requests.

  • The second call applies to an ExpressionInterceptUrlRegistry object, and specifies an "ant"-filtered "rule". There can be many rules defined, e.g. in the example antMatchers(...) and anyRequest() each start a new rule, and you can have multiple antMatchers(...) rules with different patterns.

    Rules are checked in order, until one matches the incoming request.

The master filter and the rule filter must independently match the request, in order for the request to be secured, as specified by the rule, e.g. permitAll(), denyAll(), authenticated(), hasRole("ROLE_FOO"), etc.

Andreas
  • 154,647
  • 11
  • 152
  • 247