I am using spring boot, and I have enabled the global method security in WebSecurityConfigurerAdapter by
@EnableGlobalMethodSecurity(prePostEnabled = true, order = Ordered.HIGHEST_PRECEDENCE)
And Below is my controller code
@PreAuthorize("hasAnyRole('admin') or principal.id == id")
@RequestMapping(value = "/{id}", method = RequestMethod.PUT)
public User updateUser(@PathVariable("id") String id, @Valid @RequestBody UserDto userDto)
{ ....}
However, when a non-admin user try to do a PUT request, the JSR303 validator will kick in before @PreAuthorize. For example, non-admin user ended up getting something like "first name is required" instead of "access denied". But after user supplied the first name variable to pass the validator, access denied was returned.
Does anyone know how to enforce the @PreAuthorize get checked before @Valid or @Validated?
And I have to use this kind of method-level authorization instead of url-based authorization in order to perform some complex rule checking.
@PreAuthorize
is only invoked when the method is executed. However the@Valid
is processed in preparing the execution of the method, which happens before the actual execution of the method. So this won't work. As a work around you could do manual validation instead of relying on the@Valid
annotation. – Flask