MongoDB + Node JS +基于angular色的访问控制(RBAC)

我目前正在学习MEAN堆栈,开发一个简单的TODO的应用程序,并希望为此实现基于angular色的访问控制(RBAC)。 我如何在MongoDB上设置angular色和权限?

我想要3个angular色(angular色可能看起来很有趣,但这纯粹是为了学习):

  • 超级英雄

上帝 – 类似于超级pipe理员,可以在应用程序中做任何事情。 C,R,U,D权限也适用于TODO和其他用户。 可以创build一个TODO,并将其分配给任何超级英雄或人直接。 在任何时间点更新或删除TODO或用户。

超级英雄 – 类似于pipe理员,超级力量做任何事情在他的个人数据 – C,R,U,D TODO的。 无法创build任何用户。 只能阅读和添加由GOD&TODO分配给他/她的TODO的评论。

MAN – 只能读取和添加评论给TODO分配给他/她的人。

把它们加起来 :

GOD - C,R,U,D [Global Level] SUPER HERO - C,R,U,D [Private] + R,U [Assigned to him] MAN - R,U [Assigned to him]

我明白,我需要有USERS&ROLES系列。 在哪里ROLES inturn应该有权限等我怎么把他们所有?

我喜欢给angular色的名字 – 上帝,超级英雄和人 ,容易理解。

由于您正在使用MEAN堆栈,并且许多路由validation发生在node ,所以我宁愿保持angular色表格简单。

angular色:

 { _id : 1, name : GOD, golbalPerms : true }, { _id : 2, name : SUPER HERO, privatePerms : true }, { _id : 3, name : MAN } 

用户:

 { _id : 111, name : Jesus, roleId : 1 }, { _id : 222, name : BatMan, roleId : 2 }, { _id : 333, name : Jack, roleId : 3 } 

当用户login并将user对象发送回客户端时,请确保将roleIdreplace为DB中对应的role对象。

来到节点JS上的代码:

通过完全理解你的用例,我们可以将它们分成以下几种方法 –

  • 创build用户

  • CreateTodo

  • DeleteTodo

  • ReadTodo

  • UpdateTodo
  • CommentTodo

  • AssignTodo

让我们一步一步, CreateUser

路由代码片段:

 app.all('/users', users.requiresLogin); // Users Routes app.route('/users') .post(users.hasPerms('globalPerms'), users.create); 

在您的Controller中,您可以基于input的globalPerms进行validation,如果validation允许通过调用next()创build用户,则return相应的错误消息。

现在CreateTodo && DeleteTodo

他们两个人都用相同的逻辑来处理一些小技巧。

路由代码片段:

 app.all('/todos', users.requiresLogin); // Users Routes app.route('/todos') .post(users.hasPerms('globalPerms','privatePerms'), todos.create); .delete(users.hasPerms('globalPerms','privatePerms'), todos.delete); 

创build一个Todo, globalPerms是与上帝privatePerms超级英雄 ,他们都可以被允许。

这里的窍门将在todos.delete方法中,只要确保user.id === todos.createById否则SUPER HERO可能会继续删除由GOD创build的Todos。

ReadTodo

当一个TODO被创build时,它应该有一个createById同样被存储,当一个TODO被分配给某个人时,那么createByIdassignedBy应该被logging下来。

这使得很多其他操作很容易处理。

user.role.globalPerms – 给GOD所有TODO的数据。

user.role.privatePerms – 给TODO创build他/她或分配给他/她。

user.role.globalPerms === undefined && user.role.privatePerms === undefined – 它的MAN,并给TODO的只分配给他。

UpdateTodo&CommentTodo

这是ReadTODO所做的一切的完全复制品

最后一个, AssignTodo

简单的一个, loggedInUser.id === todos.createdById然后他可以把它分配给任何人。

这里要记住两点:

  1. 由于分配部分主要发生在你的UI(Angular)前面,我已经给出了检查loggedInUser.id === todos.createdById 。 以任何方式login用户将通过读取操作看到所有TODO,并可将其分配给他/她喜欢的任何人。

  2. 确保一个超级英雄只能分配一个TODO给自己或其他超级英雄,或一个人,而不是上帝。 你如何显示分配给用户界面的选项不在这个问题的范围之内。 这只是一个头。

希望这是明确的。

注意:没有必要授予在angular色集合MAN的权限,我们pipe理了所有可能的操作。

可能的方法 – >在用户集合/模式中embeddedangular色:用户文档应具有以下内容:

 { _id : "email@mail.com", name: "lorem ipsum", role: "MAN" } 

据你的文章描述,只有上帝可以制作和分配TODO。 angular色集合可能包含以下内容:

 { _id : "MAN", globalPerm: [], privatePerm: [], assignedPerm: ["r","u"], }, { _id : "SUPER_HERO", globalPerm: [], privatePerm: ["c","r","u","d"], assignedPerm: ["c","r","u","d"], }, { _id : "GOD", globalPerm: ["c","r","u","d"], privatePerm: ["c","r","u","d"], assignedPerm: ["c","r","u","d"], } 

节点JS中间件获取用户的正确权限值后,您可能需要使用中间件。 示例表示HTTP请求路由:

 app.post('/updateTodo', permissions.check('privatePerm', 'c'), function (req, res) { // do stuff 

};

在实际执行函数体来更新TODO之前调用permissions.check。

因此,如果用户尝试更新待办事项,它将首先validation相应的权限。

这是一个非常广泛的问题,可以通过多种方式解决。

你已经添加了你正在使用MEAN栈,所以我会限制我的问题。

你没有包含在整个问题中的一件事是你使用了什么样的身份validation架构。 假设您正在使用基于令牌的身份validation,通常现在人们使用它。

我们有3种types的用户。 您可以使用不同的选项来区分令牌的types。

  1. 不同的集合(mongoDB)或Redis设置它们的存储位置
  2. encryption的令牌将具有用户的types等等。(如果你不需要在后端存储令牌,你可以解密和检查)

    • 这完全取决于用例。

现在,在允许任何用户input用户特定路线之前,请确保您首先检查标记。

 app.post('/godlevelroute', godtokencheck, callrouteandfunction); app.post('/superherolevelroute', superheroroute, callrouteandfunction); 

您必须从angular度发送标头,然后您可以从标题中取出数据,然后您可以检查该特定用户是否有权通过该路线。

比方说,上帝级别的用户login,然后他将有godleveltoken与他,我们会先检查,然后才允许他访问该路线,否则你可以只显示错误信息。

这可以是服务器端的示例标记检查function

 function checkToken(req, res, next) { var token = req.headers['accesstoken']; //access token from header //now depending upon which system you are following you can run a check }; 

节点模块build议: https : //www.npmjs.com/package/jsonwebtoken

现在来到前端部分。 你正在使用基于你写的东西的angular度,你可以在显示任何页面之前拦截令牌。

你可以通过这个博客来获得我试图解释的图片。 点击这里