我目前正在Spring Boot后端处理角色和权限。我遇到了一个问题,所以我想有人可以给我一些建议。
问题:我需要检查数据库中特定资源的用户权限,以授权或不授权访问它。我的MongoDB存储库中有两个文档,user和Dashboard。
也许一个例子可能更清楚
@PreAuthorize("hasPermission(#id , 'Dashboard', 'READ')")
@RequestMapping(value = "/dashboards/{id}", method = RequestMethod.GET)
public Dashboard getDashboard(@PathVariable("id") int id);
我的控制器接口中的一个请求看起来是这样的。我的问题是我应该将特权存储在哪里?
我想在我的Dashboard实体中有一个Map<String, PrivilegeType> privileges
(其中String是用户的Id,PrivilegeType是枚举(。这样,如果需要为特定的仪表板更新权限,我就可以轻松地管理权限。
但是,在控制器可以管理请求之前,权限计算器需要从存储库中获取仪表板,以检索该对象的所有权限,从而判断用户是否可以访问该特定的仪表板。
最后,如果安全部分获得批准,控制器将管理请求并再次检索仪表板。有很多重复的查询。
因此,我不知道权限是否应该耦合到用户,或者是否应该链接到目标资源。
这是MongoDB,如果它是一个关系数据库,这个问题不是问题,但在这里我不确定。
在我看来:
将权限存储到仪表板文档中
- pros:易于更新仪表板的所有权限(根据请求替换所有映射<UserID,privileges>(
- 缺点:当用户请求检查权限时,需要获取仪表板
将权限存储到用户文档中
- pros:只需要用户验证权限
- 缺点:当我更新仪表板权限时,需要逐个检索每个用户,以便修改自己的映射(例如Map<dashboardId,Privilege>(
我希望一切都清楚,我还没有找到答案,我提前感谢你的建议。
-
以前我不得不对类似的需求进行改进,但这不是春季启动,而是概念上相同的。I.e运行一些规则来决定用户正在访问什么资源,以及用户与该资源的关系,以决定授予该资源的该特定用户的权限。
-
我会将权限作为
dashboard
文档的一部分进行存储,原因如下- 即使是重复查询,数据库也会很快返回,因为数据库端本身缓存为几毫秒前执行的查询
- 如果性能出现问题并希望完全停止第二次调用,我可以稍后考虑在权限评估器中创建
ThreadLocal
请求上下文,然后调整我的控制器,首先检查资源是否已经在ThreadLocal
请求上下文中
注意
- 还有另一个原因,我们在过滤器中运行规则,授予动态权限,然后用注释该方法,以检查主体是否具有该动态权限。除了允许访问该方法外,我们还根据权限显示或隐藏响应中的部分。这意味着除了在入口处检查外,在准备响应时还必须再次运行该规则。通过在筛选器中运行一次规则,并使用动态权限增强主体基于静态角色的权限,我们只运行一次该规则