Issue
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?
Solution
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 version5.3
, so it's not a great alternative.
Answered By - Alexander Ivanchenko
Answer Checked By - Senaida (JavaFixing Volunteer)