简体   繁体   English

在 MongoDB 中建模访问控制

[英]Modelling Access Control in MongoDB

Does anyone have an example of modelling access control in MongoDB?有没有人有在 MongoDB 中建模访问控制的例子? The situation I'm thinking of is:我想到的情况是:

There are a set of resources, each being their own document (eg cars, people, trees etc.).有一组资源,每个资源都是它们自己的文档(例如汽车、人、树等)。

A user can gain access to a resource through an explicit grant, or implicitly by being the owner of a resource, existing in another collection (eg a role) or some other implicit ways.用户可以通过显式授权获得对资源的访问权限,或者通过成为存在于另一个集合(例如角色)中的资源的所有者或某些其他隐式方式隐式地获得访问权限。

In one collection.find() method, that could have skip and limit options applied (for pagination), is there a way to check all these explicit and implicit paths and produce a result of resources a user has access to?在一个 collection.find() 方法中,可以应用跳过和限制选项(用于分页),有没有办法检查所有这些显式和隐式路径并生成用户有权访问的资源的结果?

In MySQL we have modelled this using a grants table with resource id, granting user id, authorized user id and operation (read, write etc.).在 MySQL 中,我们使用带有资源 ID、授予用户 ID、授权用户 ID 和操作(读取、写入等)的授权表对此进行了建模。 We then, in one query, select all resources where at least one subquery is true, and the subqueries then check all the different paths to access eg one checks for a grant, one checks for ownership etc.然后,在一个查询中,选择至少一个子查询为真的所有资源,然后子查询检查所有不同的访问路径,例如一个检查授权,一个检查所有权等。

I just can't wrap my head around doing this in MongoDB, I'm not sure if it's even possible...我只是无法在 MongoDB 中做到这一点,我不确定这是否可能......

Thanks谢谢

You can't query more than one document at a time.一次不能查询多个文档。 Ideally, shouldn't access control be a part of the business logic.理想情况下,访问控制不应成为业务逻辑的一部分。 Your backend php/c#/language ought to ensure that the current request is authorized.您的后端 php/c#/language 应该确保当前请求已获得授权。 If so, then simply query the requested document.如果是这样,那么只需查询请求的文档。

If you feel, you need to implement the exact same structure in mongodb, which I suggest you don't, then you will need to embed all those fields (the ones from the other mysql tables that help you identify whether the request is authorized) in each and every document of every collection.如果您觉得需要在 mongodb 中实现完全相同的结构,我建议您不要,那么您将需要嵌入所有这些字段(来自其他 mysql 表的字段,可帮助您识别请求是否已授权)在每个集合的每个文档中。 You will be duplicating data (denormalizing it).您将复制数据(对其进行非规范化)。 Which brings the headache of ensuring that all the copies are updated and have the same value.这带来了确保所有副本都更新并具有相同值的头痛。

Edit 1:编辑1:

Lets talk about Car document.让我们谈谈汽车文件。 To track its owner, you will have owner property (this will contain the _id of the owner document).要跟踪其所有者,您将拥有owner属性(这将包含所有者文档的_id )。 To track all users who can 'use' (explicit grant) the car, you will have an array allowerdDrivers (this will contain the _id of each user document).要跟踪所有可以“使用”(显式授予)汽车的用户,您将拥有一个数组allowerdDrivers (这将包含每个user文档的_id )。 Lets assume the current user making the request belong to the 'admin' role.让我们假设发出请求的当前用户属于“管理员”角色。 The user document will have an array applicableRoles that store the _id of each role document applicable. user文档将有一个applicableRoles角色数组, applicableRoles存储每个适用角色文档的_id

To retrieve all cars that the user has access to, you only need to make two queries.要检索用户有权访问的所有汽车,您只需进行两次查询。 One to fetch his roles.一个来获取他的角色。 If he is an admin, return ALL cars.如果他是管理员,请归还所有汽车。 If he is not, then make another query where owner equals his id or allowedDrivers contains his id.如果他不是,则进行另一个查询,其中owner等于他的 id or allowedDrivers包含他的 id。

I understand your actual use case may be more complicated, but chances are there is a document-oriented way of solving that.我知道您的实际用例可能更复杂,但有可能有一种面向文档的方法来解决这个问题。 You have to realize that the way data is modelled in documents is vastly different from how you would model it in a RDbMS.您必须意识到,在文档中对数据建模的方式与在 RDbMS 中对其建模的方式大不相同。

Doing it in business logic would be painfully slow and inefficient.在业务逻辑中这样做会非常缓慢且效率低下。

How so?为何如此? This is business logic, if user a owns post b then let them do the action (MVC style), otherwise don't.这是业务逻辑,如果用户 a 拥有帖子 b,则让他们执行操作(MVC 样式),否则不执行。

That sounds like business logic to me and most frameworks consider this business logic to be placed within the controller action (of the MVC paradigm);对我来说这听起来像是业务逻辑,大多数框架都认为这个业务逻辑被放置在控制器操作中(MVC 范式); ie in PHP Yii:即在 PHP Yii 中:

Yii::app()->roles->hasAccess('some_view_action_for_a_post', $post)

I think that by doing it in the database end you have confused your storage layer with your business layer.我认为通过在数据库端执行此操作,您将存储层与业务层混淆了。

Also with how complex some role based permission actions can get the queries you commit must be pretty big with many sub selects.此外,某些基于角色的权限操作可以获得您提交的查询的复杂程度,并且必须有很多子选择。 Considering how MySQL creates and handles result sets (sub selects ARE NOT JOINS) I have a feeling these queries do not scale particularly well.考虑到 MySQL 如何创建和处理结果集(子选择不是联接),我觉得这些查询的扩展性不是特别好。

Also you have to consider when you want to change the roles, or a function that defines a role, that can access a certain object you will have to change your SQL queries directly instead of just adding the role to a roles table and assigning the object properties for that role and assigning users that role (AKA code changes).此外,您还必须考虑何时更改角色或定义角色的函数,该函数可以访问某个对象,您必须直接更改 SQL 查询,而不仅仅是将角色添加到角色表并分配对象该角色的属性并为用户分配该角色(AKA 代码更改)。

So I would seriously look into how other frameworks in other languages (and your own) do their RBAC because I think you have blurred the line and made your life quite hard with what you have done, in fact here might be a good place to start: Group/rule-based authorization approach in node.js and express.js所以我会认真研究其他语言(和你自己的)的其他框架如何做他们的 RBAC 因为我认为你已经模糊了界限并且你所做的事情让你的生活变得很艰难,事实上这里可能是一个很好的起点: node.js 和 express.js 中基于组/规则的授权方法

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM