Reputation:
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
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 :
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