user404345
user404345

Reputation:

Spring Security @PreAuthorize on controllers

I'm trying to use the url (ant based) matching along with @PreAuthorize("permitAll") on some controllers i.e.

@Controller
@RequestMapping("/register")
public class RegistrationController {
...

  @PreAuthorize("permitAll")
  @RequestMapping(method = RequestMethod.GET)
  public String register() { ... }

SecurityConfig:

@Configuration
@EnableWebMvcSecurity
@EnableGlobalMethodSecurity(prePostEnabled = true)
public class SecurityConfig extends WebSecurityConfigurerAdapter {

    @Override
    protected void configure(HttpSecurity http) throws Exception {
        // @formatter:off
        http
            .authorizeRequests()
                .antMatchers("/").permitAll()
                .anyRequest().authenticated()

I've also tried adding @EnableGlobalMethodSecurity to my MVC config:

@Configuration
@EnableGlobalMethodSecurity(prePostEnabled = true)
public class MvcConfig extends WebMvcConfigurerAdapter { ... }

But this has no effect

However I am still prompted to authenticate when hitting /register. If I add "/register" to the ant matchers it works i.e. .antMatchers("/", "/register").permitAll()

What am I missing here? It seems @PreAuthorize has no effect on my controllers

Upvotes: 12

Views: 8119

Answers (1)

Serge Ballesta
Serge Ballesta

Reputation: 148860

You cannot do that because ant matchers and @PreAuthorize work at different level.

The ant matchers works at http security level. Spring security filter looks at the request, and if it find that access should be denied, it does not even pass the request to the dispatcher servlet, and directly send a 403 error.

PreAuthorize work at method level. When a method is about to be called, an AOP proxy controls if the access should be allowed. So the 2 authorizations level are chained, instead of the second overriding the first.

Anyway, I strongly advice you not to use @PreAuthorize("hasRole('ADMIN')") on a controller :

  • it can easily be done with a simple ant matcher
  • it forces you to allow proxying on a controller, either with class proxying instead of JDK proxying or by using interfaces for controllers

IMHO, @PreAuthorize is best suited at service level, because you can mix domain objects with user granted authorities to get fine grained authorizations.

Upvotes: 26

Related Questions