我正在尝试为一个没有被广泛讨论的简单问题找到最佳解决方案。
我的应用程序有很多可以创建和编辑数据的用户。用户应该只查看和编辑他的数据,而不是其他人的数据。
想想爱丽丝,她有一个餐厅 A 和一个菜单 MenuA,鲍勃有一个餐厅 B 和一个菜单 MenuB。
我有 CRUD 餐厅和菜单的 API,我可以轻松地只授权具有正确声明和角色的登录用户。我现在想要做的是阻止 Bob 访问 Alice 的餐厅或菜单,反之亦然。
例如,Bob 应该被授权给 PUT /api/restaurants/B
但应该是未经授权的 PUT /api/restaurants/A
甚至 PUT /api/restaurants/A/menus/x
一种可能的解决方案是此处提供的解决方案 ASP.NET MVC Attribute to only let user edit his/her own content .这个解决方案需要创建一个自定义的授权属性来主动检查登录的用户是否是被访问实体的专有。实体有一个 userId 字段来检查发出请求的用户是否是数据的所有者。
这个解决方案很好很干净,但缺少一些功能。
模型中的每个实体都应该有一个 userId 字段,并且只能由所有者访问,或者对于我需要导航到授权模型的根实体的每个实体(例如,访问 Menu 我需要查询父实体 Restaurant 以进行检查)如果 MenuB 位于用户拥有的餐厅内)。
为了实现多个所有者(例如餐厅经理),逻辑将复杂得多。我也担心这里的开销,因为基本上每个调用都需要做一些查询来检查数据访问,但这可能不是问题。
有最佳实践吗?
最佳答案
您要做的是实现基于属性的访问控制或abac .
在 ABAC 架构中,您有策略执行点 (PEP) 的概念,它拦截 API 调用并确定调用是否应该通过。 PEP 将 API 调用转换为授权请求并将其发送到中央策略决策点 (PDP)。
以下架构总结了流程。
PDP 配置了一组确定允许和拒绝的策略。例如,您可以编写如下策略:
您可以使用两种语言编写策略:xacml或 alfa .
例如,在 ALFA 中,策略如下所示:
namespace restaurant{
attribute userId{
category = subjectCat
id = "restaurant.userId"
type = string
}
attribute owner{
category = resourceCat
id = "restaurant.resourceCat"
type = string
}
policy restaurant{
target clause objectType == "restaurant"
apply firstApplicable
rule ownerCanView{
target clause actionId == "view"
permit
condition userId == restaurant.owner
}
}
}
您所需要的只是使用 XACML 3.0 策略决策点。有 Java 和 .NET 实现以及商业实现。看看这个 blog post on .Net authorization .
关于.net - 如何防止用户使用 dotnet core 和 RESTful API 访问其他用户的数据?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/42654218/