Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Spring override @PreAuthorize annotation in subclass

Basically I have one Controller that is permitted for regular user and I want to have the same controller to be accessible by admin in a different path. So I thought this would work:

@RestController
@PreAuthorize("hasRole('USER')")
@RequestMapping(value = "/user")
public class UserController {
    @RequestMapping(value = "/name", method = RequestMethod.GET)
    public String getName() {
        return service.getCurrentUserName();
    }
}

@RestController
@PreAuthorize("hasRole('ADMIN')")
@RequestMapping(value = "/admin")
public class UserController extends UserController{
}

But I can call both /user/name and /admin/name with the USER role. So it kind of ignores the PreAuthorize annotation on the subclass.

Is there any way to re-use the UserController methods and just add a different security PreAuthorize to them without rewriting them for Admin?

like image 519
danial Avatar asked Jan 19 '26 13:01

danial


1 Answers

The controller methods are registered in superclass, so the superclass annotation applies.

The only way I know to have a kind of dynamic annotation, is to use a #root inside the @PreAuthorize. You could modify the parent class that way :

@RestController
@PreAuthorize("hasRole(#root.this.requiredRole)")
@RequestMapping(value = "/user")
public class UserController {
    protected String getRequiredRole() {
        return "USER";
    }
    ...
}

And for the child class :

@RestController
@RequestMapping(value = "/admin")
public class AdminController extends UserController {
    protected String getRequiredRole() {
        return "ADMIN";
    }
    ...
}

That way, the methods of the parent class will correctly require ADMIN role when called for a AdminController object, since the string value of @PreAuthorize will be preprocessed by SpEL, while still requiring USER role for a true UserController.

like image 181
Serge Ballesta Avatar answered Jan 22 '26 07:01

Serge Ballesta