【问题标题】:What is the best way to implement roles and permission in Express REST Api在 Express REST Api 中实现角色和权限的最佳方式是什么
【发布时间】:2016-12-18 00:06:56
【问题描述】:

我需要专家意见来在 Express js 中实现角色和权限。我计划使用 Express js 开发 Restful Api,但没有获得足够的信息来实现角色和权限,尽管有很多选项可用于身份验证和授权。

【问题讨论】:

  • 您需要一个表,将每个角色映射到每个资源到每个权限。在需要用户和资源的每个资源上添加一个中间件,如果所需的权限设置为 true,则检查数据库。如果是,则您的用户拥有该资源的正确权限。
  • 也有这样做的例子。查看 [node_acl}(npmjs.com/package/acl) 之类的模块,您可以使用或阅读该模块作为您自己方法的灵感。
  • 谢谢@MatthewBakaitis

标签: node.js rest express


【解决方案1】:

创建表格

首先,您需要创建将保存角色、权限和资源之间关联的表:

  1. 创建角色表('Admin'、'User'、'Guest')
  2. 创建资源表('Users'、'Projects'、'Programs')
  3. 创建权限表('Create'、'Read'、'Write'、'Delete'、'Deny')
  4. 创建一个以所有三个表作为源的联结表

您可能不需要权限表的那种粒度,但有些人喜欢它。例如,您实际上并不需要“拒绝”,因为您只需检查 Read != true。

现在,当您想要某个角色对资源的权限时,您只需查找 role_id 和 resource_id 并检查哪些权限设置为 true。

创建中间件

由于您使用的是 express,中间件将很容易添加。例如,假设您有一个名为 users 的路由器:

users.post('/', getAuth, handleUserPost)

假设您在请求中有某种令牌来识别发布帖子的用户,并将用户实例附加到请求对象,您可以这样做:

getAuth = function (req, res, next) {
  if(req.user) { 
    db.getPerms({role_id: req.user.role_id, resource_id: req.resource.id})
       .then(function(perms){
          var allow = false;
          //you can do this mapping of methods to permissions before the db call and just get the specific permission you want. 
          perms.forEach(function(perm){
              if (req.method == "POST" && perms.create) allow = true;
              else if (req.method == "GET" && perms.read) allow = true;
              else if (req.method == "PUT" && perms.write) allow = true;
              else if (req.method == "DELETE" && perm.delete) allow = true;

          })
          if (allow) next();
          else res.status(403).send({error: 'access denied'});
       })//handle your reject and catch here
   } else res.status(400).send({error: 'invalid token'})
}

该代码只是为了这个例子而粗略的,所以我不会去复制和粘贴它,但它应该给你正确的想法。

【讨论】:

  • 如果可能的话,请你给我解释一下
  • 你能推荐任何关于 Node 中这种类型实现的文献吗?
  • 感谢@Dave,但这就是高并发 API 实现其流程的方式,除了他们可能将其用作内存而不是 DB 命中
  • 为什么你认为 qr 使用了类似 RDBMS 的数据库?你说的是“桌子”。为什么要将不同的规则及其权限存储在数据库中,为什么不在代码中创建模型?
  • 回到简单的基础
【解决方案2】:

Node.js 中的角色权限


第 1 部分:什么是角色和权利?

角色权限的实现是任何软件的重要组成部分。角色是一个职责位置,每个职责都享有被赋予的某些权利。少数角色之间可能存在一些共同的权利,而某些权利可能严格属于特定角色。

Rights是一个角色被授权访问的Urls。因此有必要在db中创建一个集合来存储角色的权限信息。 我们的角色集合架构为

const mongoose = require('mongoose');
const Schema = mongoose.Schema;
const RoleSchema = new Schema({
  roleId:{
    type:String,
    unique:true,
    required:[true,"Role Id required"]
  },
  type:{
    type:String,
    unique:true,
    required:[true,"Role type is required"]
  },
  rights:[{
    name: String,
    path: String,
    url: String
  }]
});
module.exports = Role = mongoose.model('role',RoleSchema);

现在请记住,假设存在的每个角色都在角色集合中并且属于上述模式类型。

在对象的架构权限数组中,我们看到对象有键:

  • name(用于 url 的名称,例如“set-username”)
  • 路径(对于基本路径命中“/users/”)
  • url(请求的url或完整路径“/users/set-username”)

因此,如果具有角色 user 的用户有权更改用户名,那么他可以点击 url /users/set-username.然而,流浪者将无法访问此网址。像管理员和超级管理员这样的高级角色在逻辑上应该可以访问所有低级角色权限(url)。

在实际应用中的作用是:-

  1. Wanderer刚刚访问我们网站的人。他应该能够访问所有公共路线。所有人都可以访问的简单网址/公共网址因此不需要为此设置单独的角色,因为它不是任何经过验证的权利。)
  2. 访客已注册但未验证的人说电子邮件未验证)。
  3. 用户拥有经过验证的电子邮件的人
  4. 管理员超级管理员验证后成为管理员。他享有大部分权利
  5. 超级管理员应用大师。他享有一些更高级的权限。更多权限然后管理员

到目前为止,我们已经了解什么是正确的,以及它是如何映射到角色的。


第 1.5 部分:注册网址/配置网址

这里有一个名为registeredUrls.js 的文件,类似于:

module.exports = {
    simple:{
        "/":[""],
        '/users/':["login","register"],
    },
    auth:{
        //admin
        '/admin/': ['load-users' , 'set-new-password','delete-user'],
        '/teacher/':["add-teacher","delete-teacher","edit-teacher"],
        '/student/':["add-student","delete-student","edit-student","test-result"],
        
        //user
        '/test/':["view-test","submit-test"],
        '/profile/': ['change-username', 'update-profile-data',  'set-new-password', 'upload-pic', 'update-social-links'],
        '/teacher/':['load-teacher'],
        '/student/':['load-student']

    }
}

类似 confgUrls.js

const configUrls= {
    '/roles/': ['get-rights', 'create', 'update-rights', 'load', 'delete', 'assign']
}
module.exports = configUrls;

第 2 部分:创建超级管理员

这是应用程序中最重要的部分。每当服务器第一次启动或重新启动/重新启动时,都会发生此步骤。在 config/init.js 中遵循程序:

  1. 将所有简单的 urls(public) 和 Auth Urls(admin & users) & super-admin-specific urls 加载到 superAdminRights[]。
  2. 如果不存在,则运行一个函数来创建一个角色为 superadmin 的用户。
  3. 如果找到,获取类型为:“superadmin”的角色:将其权限替换为新权限(superAdminRights)。否则:创建类型为:“superadmin”的角色,然后填写其权限(superAdminRights)。

在此函数调用结束时,我们始终确定应用程序中有一个超级管理员,其所有复杂的 url/权限都已初始化。


第 3 部分:超级管理员特定网址

这些是仅由超级管理员享有的权利,必须与注册的 url 文件并行维护在单独的文件中。这些包括映射仅由超级管理员使用的路由的 url 权限。 在这里,我们有创建角色、加载角色、获取角色 ID 的权限、更新角色 ID/角色类型的权限、分配角色给用户、删除角色的路线。

对于代码中的每个用户,我们需要将他们的角色从访客更改为用户(例如在电子邮件验证之后)。或者通过超级管理员使用分配角色 url 将访客/用户更改为管理员。然后使用路由更新权限更新管理员权限。

该过程确保每个角色都有一个集合文档并在那里填写权限。


第 4 部分:身份验证器中间件

这是我们 RBACS 逻辑的核心。这里我们使用一个遵循流程的中间件:

1.使用 auth-urls(registeredUrls.js) & super-admin-specific-urls(confgUrls.js) 和不同 [SIMPLE_URLS] 中的简单 url 在 [AUTH_URLS] 中填写所有需要身份验证的 url。

2.然后检查 if (AUTH_URLS.indexOf(request.url) > -1){3rd step} else if (SIMPLE_URLS.indexOf(request.url)>-1){then it is public url so simple allow next()} else {响应未知网址}

3.在这一步中,我们知道在 AUTH_URLS 中请求的 url 因此需要令牌检查授权令牌标头,如果找到则从其中提取令牌然后{第四步}。如果没有找到授权标头响应“所需令牌”/“未知”。

4.找到令牌,现在验证此令牌是否具有有效会话。如果是 {5th step} else token session not found 再次登录。 5。验证 jwt 令牌,如果已验证则验证它{6.step} 否则响应“无效的 jwt 令牌”。

6.直到现在正确的 url 请求和令牌会话存在和 jwt 有效令牌。现在使用会话中的角色类型信息(存储在会话中是用户和令牌的基本信息)在角色中找到此用户会话角色-type 因此我们有它的权限[]。现在看看 request.url 是否包含在权限[]中。如果找到 {7th step} else {reponse "role not found/unknown user"}。

7.如果找到,则 {有权访问此网址 next() } else { 响应“拒绝访问”}

【讨论】:

    猜你喜欢
    • 2015-11-25
    • 1970-01-01
    • 2019-10-31
    • 2017-10-04
    • 2017-08-15
    • 2011-06-21
    • 2017-08-12
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多