Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to check security acess (@Secured or @PreAuthorize) before validation (@Valid) in my Controller?

Tags:

here is my Controller code :

@PreAuthorize("hasRole('CREATE_USER')")
@RequestMapping(method = RequestMethod.POST, produces = MediaType.APPLICATION_JSON_VALUE, consumes = MediaType.APPLICATION_JSON_VALUE)
@ResponseBody
public UserReturnRO createUser(@Valid @RequestBody UserRO userRO) throws BadParameterException{

    return userService.createUser(userRO);
}

My need is when a client without the appropriate role tries to create a user, the controller responds "Not authorized" even if the data sent are not valid. Instead of that, if the client (without the appropriate role) tries to create a user with wrong data, my controller responds with the @Valid message (ex : "password cannot be empty"), while I want it responds "not authorized".

In the PreAuthorized Interface we can find this sentence :

Annotation for specifying a method access-control expression which will be evaluated to decide whether a method invocation is allowed or not.

but it seems that it's not the case.

like image 390
stephane06 Avatar asked Apr 01 '14 08:04

stephane06


People also ask

What's the difference between @secured and @PreAuthorize in Spring Security?

The real difference is that @PreAuthorize can work with Spring Expression Language (SpEL). You can: Access methods and properties of SecurityExpressionRoot . (Advanced feature) Add your own methods (override MethodSecurityExpressionHandler and set it as <global-method-security><expression-handler ... /></...> ).

Which of the following are annotations that can be used to secure a spring controller method?

Method-level security is implemented by placing the @PreAuthorize annotation on controller methods (actually one of a set of annotations available, but the most commonly used). This annotation contains a Spring Expression Language (SpEL) snippet that is assessed to determine if the request should be authenticated.

How do you validate a role in spring boot?

The first way to check for user roles in Java is to use the @PreAuthorize annotation provided by Spring Security. This annotation can be applied to a class or method, and it accepts a single string value that represents a SpEL expression. Before we can use this annotation, we must first enable global method security.

How does secured annotation work?

The @Secured annotation is used to specify a list of roles on a method. So, a user only can access that method if she has at least one of the specified roles.


1 Answers

You can not do this directly, since @Valid is processed before an actual method call and as a result before @PreAuthorize.

But what you can do instead is to inject BindingResult just right after your model (userRO) and in doing so - take control of validation process. Then check if BindingResult has some errors and if so return bad request response (similar to what spring does).

Example:

@ResponseBody
@RequestMapping(method = RequestMethod.POST, produces = MediaType.APPLICATION_JSON_VALUE, consumes = MediaType.APPLICATION_JSON_VALUE)
@PreAuthorize("hasRole('CREATE_USER')")
public ResponseEntity<?> createUser(@RequestBody @Valid UserRO userRO, BindingResult result) {
    if (result.hasErrors()) {
        return ResponseEntity.badRequest().body(result.getAllErrors());
    }
    return ResponseEntity.ok(userService.createUser(userRO));
}
like image 115
Bohdan Levchenko Avatar answered Sep 22 '22 08:09

Bohdan Levchenko