Gökhan Öner (Migrated from SEC-3104) said:
@PreAuthorize, @PostAuthorize, @Secured annotation can have a parameter to point custom message property in order to set detailed & more user friendly exception messages.
This could also be done by providing a param. to define an class name that extends AccessDeniedException to raise to you let users handle the rest.
This way, while processing complex rules like
@PreAuthorize("record.createuser != authentication.getName()")
We can get a defined error like
"You cannot process a record that you created."" etc. insted of "Access is denied"
Comment From: marcusdacoregio
I wonder what are the advantages of doing this instead of calling a custom bean that does the logic:
@RestController
class HelloController {
@GetMapping("/hello")
@PreAuthorize("@authorization.check()")
public String hello() {
return "hello";
}
@ExceptionHandler(CustomAccessDenied.class)
public ResponseEntity<String> handleCustomAccessDenied(CustomAccessDenied ex) {
return ResponseEntity.status(403).body(ex.getMessage());
}
}
@Component
public class Authorization {
public boolean check() {
throw new CustomAccessDenied();
}
}
static class CustomAccessDenied extends AccessDeniedException {
public CustomAccessDenied() {
super("CustomAccessDenied");
}
}
Comment From: jzheaux
As for 6.3, this can be done in the following way:
Option 1
Publish a MethodAuthorizationDeniedHandler:
@Component
public class CustomException implements MethodAuthorizationDeniedHandler {
@Override
Object handleDeniedInvocation(MethodInvocation invocation, AuthorizationResult result) {
throw new AuthorizationDeniedException("my custom message");
}
}
And then use it in an annotation on the method like so:
@PreAuthorize(...)
@HandleAuthorizationDenied(handlerClass=CustomException.class)
public String method() { ... }
Option 2
Or, you can use Spring's meta-annotation support to make this more flexible. Define a new annotation:
...
@HandleAuthorizationDenied(handlerClass=CustomException.class)
public @interface CustomErrorMessage {
String value() default "access is denied";
}
Publish a MethodAuthorizationDeniedHandler:
@Component
public class CustomException implements MethodAuthorizationDeniedHandler {
@Override
Object handleDeniedInvocation(MethodInvocation invocation, AuthorizationResult result) {
String message = AnnotationUtils.findAnnotation(invocation.getMethod(), CustomErrorMessage.class).value();
throw new AuthorizationDeniedException(message);
}
}
And then use:
@PreAuthorize(...)
@CustomMessage("my custom message")
public String method() { ... }