在Express REST Api中实现角色和权限的最佳方法是什么

zah*_*ool 18 rest node.js express

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

Dav*_*and 22

创建表格

首先,您需要创建包含角色,权限和资源之间关联的表:

  1. 创建角色表('Admin','User','Guest')
  2. 创建资源表('用户','项目','程序')
  3. 创建权限表('创建','读','写','删除','拒绝')
  4. 创建一个包含所有三个表作为源的联结表

您可能不需要权限表的那种粒度,但有些人喜欢它.例如,你真的不需要'拒绝',因为你只需要检查Read!= true.

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

创建中间件

由于您使用快速,因此中间件很容易添加.例如,假设您有一个名为users的路由器:

users.post('/', getAuth, handleUserPost)
Run Code Online (Sandbox Code Playgroud)

假设您在请求上有某种标记,用于标识发布帖子的用户,并将用户实例附加到请求对象,您可以执行以下操作:

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'})
}
Run Code Online (Sandbox Code Playgroud)

这个代码只是为了这个例子而被粗暴对待,所以我不会复制并粘贴它,但它应该给你正确的想法.


Ani*_*Jha 15

Node.js 中的角色权限


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

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

权限是角色被授权访问的Url。因此有必要在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);
Run Code Online (Sandbox Code Playgroud)

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

在对象的模式权限数组中,我们看到对象具有键:

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

因此,如果具有角色user 的用户有权更改用户名,则他可以点击 url 。 /users/set-username但是,漫游者将无法访问此 url。像 admin 和 superadmin 这样的更高角色在逻辑上应该可以访问所有较低角色权限(url)。

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

  1. 流浪者刚刚访问我们网站的人。他应该能够访问所有公共路线。所有人都可以访问的简单网址/公共网址因此不需要为此设置单独的角色,因为它没有任何经过身份验证的权利。
  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']

    }
}
Run Code Online (Sandbox Code Playgroud)

同样 confgUrls.js

const configUrls= {
    '/roles/': ['get-rights', 'create', 'update-rights', 'load', 'delete', 'assign']
}
module.exports = configUrls;
Run Code Online (Sandbox Code Playgroud)

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

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

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

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


第 3 部分:超级管理员特定的 URL

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

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

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


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

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

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

2. 然后检查是否 (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 { 响应未知 url}

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

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

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

7. 如果找到,则{可以访问此 url next() } else { 响应“拒绝访问”}