MongoDB + 节点 JS + 基于角色的访问控制 (RBAC)

MongoDB + Node JS + Role Based Access Control (RBAC)

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

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

GOD - 类似于超级管理员,可以在应用程序中做任何事情。 TODO 和其他用户的 C、R、U、D 权限。可以创建一个 TODO 并将其直接分配给任何 SUPER HERO 或 MAN。随时更新或删除 TODO 或用户。

SUPER HERO - 类似于管理员,拥有对个人数据执行任何操作的超能力 - C、R、U、D 用于 TODO。无法创建任何用户。只能阅读和添加由 GOD 创建并分配给 him/her.

的 TODO 的评论

MAN - 只能阅读分配给 him/her 的 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 反过来应该有 PERMISSIONS 等。我如何连接它们?

可能的方法-> 在用户中嵌入角色 collection/schema: 用户文档应包含以下内容:

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

据您的 post 描述,只有上帝才能制定和分配 TODO。 角色集合可能包含以下内容:

{
    _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"],
}

Node JS 中间件 在为用户获得正确的权限值后,您可能想要使用中间件。 示例快速 HTTP 请求路由:

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

};

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

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

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

您已经补充说您使用的是 MEAN 堆栈,因此我的问题仅限于此。

您没有在整个问题中包括的一件事是您使用的是哪种身份验证架构。假设您正在使用基于令牌的身份验证,如今人们通常都在使用它。

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

  1. 不同的 Collection (mongoDB) 或 Redis 设置它们的存储位置
  2. 加密后的token也会有用户的类型等。(如果你不需要在后端存储token,这个就派上用场了,你可以直接解密和检查)

    • 这完全取决于用例。

现在,在允许任何用户进入用户特定路由之前,请确保您首先检查令牌。

示例

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

您必须从 angular 发送令牌到 header 然后您可以从 header 中取出数据然后您可以检查该特定用户是否有权通过那条路线与否。

假设神级用户登录,然后他将拥有 godleveltoken,我们将在允许他访问该路由之前先进行检查,否则您可以只显示错误消息。

这可以是您在服务器端的示例令牌检查功能

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
};

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

现在进入前端部分。根据您所写的内容,您正在使用 angular,您可以在显示任何页面之前拦截令牌。

您可以浏览此博客以获得我试图解释的内容的图形表示。 Click Here

我喜欢给角色起的名字-GOD, SUPER HERO & MAN,简单易懂

由于您使用的是 MEAN 堆栈,并且大部分路由验证都是在 node 上进行的,所以我更愿意保持角色 table 简单。

角色:

{
_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
}

当用户登录并将 user 对象发送回客户端时,确保将 roleId 替换为来自数据库的相应 role 对象。

即将在 Node JS 上编写代码:

通过完全了解您的用例,我们可以将它们分为以下方法 -

  • 创建用户

  • CreateTodo

  • DeleteTodo

  • ReadTodo

  • 更新待办事项
  • CommentTodo

  • AssignTodo

一步步来,CreateUser.

路线代码片段:

app.all('/users', users.requiresLogin);

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

在您的控制器中,您可以根据输入 globalPerms 进行验证,如果验证通过,则允许通过调用 next() 否则 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);

对于创建 Todo,globalPermsGOD & privatePermsSUPER HERO,两者其中一个是允许的。

这里的技巧将在todos.delete方法中,只需确保user.id === todos.createById否则SUPER HERO可能会继续删除GOD创建的Todos。

阅读待办:

创建 TODO 时,它应该存储 createById 同样,当 TODO 分配给某人时 [= =26=] 和 assignedBy 也应该被记录下来。

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

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

user.role.privatePerms - 给 TODO 的创建者 him/her 或分配给 him/her.

user.role.globalPerms === undefined && user.role.privatePerms === undefined - 它的 MAN 和只分配给他的 TODO。

更新待办和评论待办

这是 ReadTODO 所做的 DIY 的精确复制

最后一个,AssignTodo :

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

这里要记住两件事:

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

  2. 确保 SUPER HERO 只能将 TODO 分配给自己或其他 SUPER HERO 或 MAN,但不能分配给 GOD。如何在 UI 前面显示分配给选项超出了这个问题的范围。这只是一个提醒。

希望这是清楚的。

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