【问题标题】:Is it possible to prefetch database object from auth/custom annotation in Spring boot是否可以在 Spring Boot 中从 auth/custom 注释中预取数据库对象
【发布时间】:2022-10-23 19:45:20
【问题描述】:
我的 Spring MVC 控制器中有以下端点:
@RestController
public class ToolsController {
@GetMapping("/v1/auth-check/....id....")
@RolesAllowed(...)
@MyCustomPermissions(...)
public MyResult checkAuth(...., int databaseId, ....) {
这里的角色允许是一个标准注释,它检查用户数据并防止在没有权限的情况下调用方法。
现在我还想借助包含在由参数databaseId 标识的数据库对象中的数据来检查权限。我可以从某处读取此对象,以便我的注释也阻止调用方法吗?
我可以在HandlerInterceptorAdapter#preHandle 中单独解析请求
这很糟糕,因为我将复制 Spring 的工作。还有其他机制吗?
【问题讨论】:
标签:
java
spring
spring-security
interceptor
【解决方案1】:
使用@PreAuthorize,它允许您定义一个SpEL 来引用任何bean 中的方法,该方法将在调用方法进行权限检查之前执行。权限检查方法应该返回一个布尔值,true 表示允许,false 表示不允许。
在该 SpEL 中,您可以使用 @bean 引用 bean 并使用 #foo 或 @P 访问 @PreAuthorize 保护的方法的参数。(here 上的文档)
就像是 :
@GetMapping("/v1/auth-check/....id....")
@PreAuthorize("@authzService.isAllow(#databaseId)")
public MyResult checkAuth(...., int databaseId, ....) {
}
它将查找名称为authzService 的bean 并执行其isAllow() 以进行权限检查。
@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.
******************************************/
}
}
【解决方案2】:
如果您所指的对象“数据库对象”是checkAuth() 返回的结果,那么您肯定可以检查它的内容@PostAuthorize。如果作为参数提供的 SpEl 表达式不匹配,则请求处理将失败并出现异常。
它看起来像这样:
@PostAuthorize("returnObject.databaseId ... <- your-conditional-logic-here")
提醒:要启用此注释,@EnableGlobalMethodSecurity 的 prePostEnabled 属性(注释配置类) 需要设置为true (我想你知道这一点,但随机读者可能不会):
@EnableGlobalMethodSecurity(prePostEnabled=true)
如果您没有引用结果对象,那么您可以检索它“数据库对象”就在 SpEl 表达式中,因为我们可以自由地使用任何 Bean 并调用它们的方法。所以它仍然可以使用@PostAuthorize。
另外,值得注意的是:
- 最好保持 SpEl 表达式尽可能简单,因为它很难测试。
-
HandlerInterceptorAdapter 自发布版本5.3 以来已弃用,因此它不是一个很好的选择。