Home > Enterprise >  Is it possible to prefetch database object from auth/custom annotation in Spring boot
Is it possible to prefetch database object from auth/custom annotation in Spring boot

Time:10-23

I have the following endpoint in my Spring MVC controller:

@RestController
public class ToolsController {

    @GetMapping("/v1/auth-check/....id....")
    @RolesAllowed(...)
    @MyCustomPermissions(...)
    public MyResult checkAuth(...., int databaseId, ....) {

Here roles allowed is a standard annotation, which checks with user data and prevent method from being called without permissions.

Now I want additionally to check permissions with the help of a data, which is contained in a database object, identified by parameter databaseId. Can I read this object from somewhere so that my annotation also prevent method from being called?

I can parse request separately in HandlerInterceptorAdapter#preHandle

This is bad because I will duplicate Spring's work. Are there any other mechanisms?

CodePudding user response:

If the object you're referring to as "database object" is the result returned by checkAuth() then sure you can examine its contents @PostAuthorize. If a SpEl expression provided as an argument would not match, then request processing would fail with an exception.

It would look like this:

@PostAuthorize("returnObject.databaseId ... <- your-conditional-logic-here")

Reminder: to make this annotation enabled, prePostEnabled attribute of the @EnableGlobalMethodSecurity (which annotates configuration class) needs to be set to true (I guess you're aware of this, but a random reader might be not):

@EnableGlobalMethodSecurity(prePostEnabled=true)

In case if you didn't refer to the resulting object, then you can retrieve this "database object" right inside the SpEl-expression because we're free to use any Beans and invoke their methods. So it still can be using @PostAuthorize.

Also, it's worth noticing:

  • That it's better keep SpEl-expression as simple as possible, since its hard to test.
  • HandlerInterceptorAdapter is deprecated since release version 5.3, so it's not a great alternative.

CodePudding user response:

Use @PreAuthorize which allows you to define a SpEL to refer to a method in any bean that will be executed before a method is called for permission checking. The permission checking method should return a boolean which true means allow while false means disallow.

In that SpEL , you can use @bean to refer to a bean and use #foo or @P to access the parameters of the method that @PreAuthorize protects.(docs at here)

Something like :

@GetMapping("/v1/auth-check/....id....")
@PreAuthorize("@authzService.isAllow(#databaseId)")
public MyResult checkAuth(...., int databaseId, ....) {

}

which will look for a bean which the name is authzService and execute its isAllow() for permission checking.

@Service
public class AuthzService{

    public boolean isAllow(int databaseId){
        /******************************************
          Do the checking here....
          Use SecurityContextHolder.getContext().getAuthentication() to access the current user object such that you can check their roles. 
         ******************************************/
    }
} 
  • Related