What is the difference between using @PreAuthorize(hasRole(...)) and using requestMatchers(...).hasRole(...)? Does it have any impact on security? And what is better to use?
I've seen that both solutions are used, so I don't know which one is better.
@GetMapping("/companies")
@PreAuthorize("hasAnyRole('USER','ADMIN')")
public ResponseEntity<CompanyDto> getCompanyById(@PathVariable("companyId") Long companyId) {
CompanyDto companyDto = companyService.getCompanyById(companyId);
return new ResponseEntity<>(companyDto, HttpStatus.OK);
}
or
SecurityConfig
.requestMatchers(HttpMethod.GET, "/companies").hasAnyAuthority(ADMIN, USER)
@PreAuthorize
is a method-level security annotation as defined in the respective documentation:
Annotation for specifying a method access-control expression which will be evaluated to decide whether a method invocation is allowed or not.
On the other hand, using the requestMatchers
is done in the HTTP security configurations (as shown in the securityFilterChain
example)! In general, it matches the incoming requests based on specific patterns or alike, for example the security constraint of the request having a role - thus requestMatchers().hasRole()
is evaluated at the time of the HTTP request, before the controller method is even invoked!
@PreAuthorize
is better.requestMatchers().hasRole()
is easier.Most often than not, a combination of both of them is useful. For example, a requestMatcher
to secure general endpoints and then @PreAuthorize
for more complex checks.