在MongoDB中建模访问控制

5
有人有在MongoDB中建模访问控制的示例吗? 我考虑的情况是:
存在一组资源,每个资源都是其自己的文档(例如汽车、人、树等)。
用户可以通过显式授权或隐式方式访问资源,例如成为资源的所有者,存在于另一个集合中(例如角色)或其他隐含方式。
在一个collection.find()方法中,可以应用skip和limit选项(进行分页),是否有一种方法可以检查所有这些显式和隐式路径,并产生用户可以访问的资源结果?
在MySQL中,我们使用授权表来对其进行建模,其中包含资源ID,授权用户ID,授权用户ID和操作(读取、写入等)。然后,在一个查询中,选择至少一个子查询为true的所有资源,然后子查询检查访问不同路径的所有不同方式,例如一个查询授权,一个查询所有权等。
我仍无法理解如何在MongoDB中执行此操作,甚至不确定是否可能...
2个回答

3
您一次不能查询多个文档。理想情况下,访问控制应该是业务逻辑的一部分。您的后端php/c#/语言应确保当前请求得到了授权。如果是这样,那么只需查询请求的文档即可。
如果您感觉需要在mongodb中实现完全相同的结构(我建议您不要这样做),那么您需要在每个集合的每个文档中嵌入所有那些字段(来自其他mysql表格的字段,用于确定请求是否被授权)。您将会复制数据(去规范化)。这将带来一个问题:如何确保所有副本都更新并具有相同的值。
编辑1: 我们来谈谈汽车文档。为了跟踪它的所有者,您将拥有owner属性(它将包含所有者文档的_id)。为了跟踪所有可以“使用”(明确授权)汽车的用户,您将拥有一个名为allowerdDrivers的数组(它将包含每个用户文档的_id)。假设当前进行请求的用户属于'admin'角色。用户文档将有一个名为applicableRoles的数组,其中存储了每个适用角色文档的_id。
要检索用户具有访问权限的所有汽车,您只需要进行两次查询。第一个查询是为了获取他的角色。如果他是管理员,则返回所有汽车。如果不是,则进行另一个查询,其中owner等于他的id或allowedDrivers包含他的id。
我理解您的实际用例可能更加复杂,但很有可能有一种文档导向的方法来解决这个问题。您必须意识到,在文档中建模数据的方式与在关系数据库管理系统中建模数据的方式截然不同。

我认为这可能是情况。在业务逻辑中执行会非常缓慢和低效。在搜索或列出这些资源的情况下,您需要全部读取它们,或逐个读取它们,并对它们应用所述业务逻辑,如果它们失败则将其丢弃并继续读取,直到达到分页限制。虽然更加复杂,但在查询时在数据层面上执行是值得的。没有事务的情况下重复似乎很危险,因为您希望全部更新或全部不更新。也许MongoDB对我们的用例并不适合。 - Tyler
更新了我的回答。只是一个建议,你可能想在MongoDB谷歌用户组上发这个问题。我相信文档数据库在大多数应用中可以像或者比其他类型的数据库使用得更好。而且你的应用可能不是例外。 - Amith George
接受这个答案 - 对我来说最重要的是可以执行多个查询 :) - Tyler

0
在业务逻辑中这样做会非常缓慢和低效。
为什么呢?这是业务逻辑,如果用户a拥有帖子b,则让他们执行操作(MVC风格),否则不允许。
对我来说,这听起来像是业务逻辑,大多数框架都认为这种业务逻辑应该放在控制器操作中(MVC范例);例如在PHP Yii中:
Yii::app()->roles->hasAccess('some_view_action_for_a_post', $post)

我认为通过在数据库端进行操作,您已经混淆了存储层和业务层。

此外,由于基于角色的权限操作有时会变得非常复杂,您提交的查询可能会非常大,并包含许多子选择。考虑到MySQL创建和处理结果集的方式(子选择不是连接),我觉得这些查询的可扩展性并不特别好。

此外,当您想要更改角色或定义可以访问某个对象的角色的功能时,您将不得不直接更改SQL查询,而不仅仅是将角色添加到角色表中,并为该角色分配对象属性并将用户分配给该角色(即代码更改)。

因此,我建议您认真研究其他语言(以及您自己的语言)中的其他框架如何处理RBAC,因为我认为您已经模糊了界限,并且使自己的生活变得相当困难。实际上,这里可能是一个很好的起点:Node.js和Express.js中的基于组/规则的授权方法


确定用户是否有访问特定对象的权限并不是问题,问题在于查询用户可以访问的对象列表。如果数据库中有数千个项目,并且您想查询用户可以访问的项目,则逐个遍历每个项目并调用hasAccess将会非常慢。 - stevex
@stevex,那你正在错误地使用RBAC,相反地,你应该拥有例如edit-posts的权限,然后在代码中检测是否可以编辑该帖子,权限只用于访问操作而不是对象。 - Sammaye
@stevex 我应该澄清一下,RBAC和优化业务逻辑以确定用户是否拥有对象是两件不同的事情。这篇文章已经过去很多年了,而且在我回答之后,OP似乎已经在上面的答案中澄清了他们的观点。 - Sammaye

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接