Node.js 在Express REST Api中实现角色和权限的最佳方式是什么

Node.js 在Express REST Api中实现角色和权限的最佳方式是什么,node.js,rest,express,Node.js,Rest,Express,我需要一种专家意见来实现ExpressJS中的角色和权限。我计划使用expressjs开发restfulapi,但是没有获得足够的信息来实现角色和权限,尽管有很多选项可用于身份验证和授权 创建表格 首先,您需要创建包含角色、权限和资源之间关联的表: 创建角色表('Admin'、'User'、'Guest') 创建资源表(“用户”、“项目”、“程序”) 创建权限表(“创建”、“读取”、“写入”、“删除”、“拒绝”) 创建一个连接表,将所有三个表作为源 权限表可能不需要这种粒度,但有些人喜欢它。例如

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

创建表格

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

  • 创建角色表('Admin'、'User'、'Guest')
  • 创建资源表(“用户”、“项目”、“程序”)
  • 创建权限表(“创建”、“读取”、“写入”、“删除”、“拒绝”)
  • 创建一个连接表,将所有三个表作为源
  • 权限表可能不需要这种粒度,但有些人喜欢它。例如,您实际上不需要“拒绝”,因为您只需检查读取!=对

    现在,当您需要角色对资源的权限时,只需查找role\u id和resource\u id并检查哪些权限设置为true

    创建中间件

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

    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.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);
    
    现在请记住,存在的每个角色都在角色集合中,并且属于上述模式类型

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

    • 名称(用于url名称,如“设置用户名”)
    • 路径(对于基本路径命中“/users/”)
    • url(请求的url或完整路径)/用户/设置用户名)
    因此,如果角色为user的用户有权更改用户名,那么他可以点击url
    /users/set username
    。但是,漫游者将无法访问此url。高级角色(如管理员和超级管理员)在逻辑上应该可以访问所有低级角色权限(url)

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

  • 漫游者(刚刚访问我们网站的人。他应该能够访问所有公共路线。所有人都可以访问的简单URL/公共URL因此不需要为此设置单独的角色,因为这不是任何经过身份验证的权利。)
  • 来宾(已注册但未验证的人说电子邮件未验证)
  • 用户(拥有已验证电子邮件的人)
  • 管理员(由SuperAdmin验证后成为管理员,享有大部分权限)
  • 超级管理员(应用程序大师。他享有一些更复杂的权限。权限比管理员更多)
  • 到目前为止,我们已经了解了什么是正确的,以及它是如何映射到角色的


    第1.5部分:注册URL/Config URL

    这里有一个名为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中,请遵循以下过程:

  • 将所有简单URL(公共)和验证URL(管理员和用户)以及超级管理员特定URL加载到超级管理员权限[]
  • 然后运行一个函数来创建角色为superadmin的用户(如果不存在)
  • 如果找到“超级管理员”类型的角色:将其权限替换为新权限(超级管理员权限)。否则:创建“超级管理员”类型的角色,然后填充其权限(超级管理员权限)
  • 在这个函数调用结束时,我们始终确保应用程序中有一个超级管理员,其所有复杂的URL/权限都已初始化


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

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

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

    该流程确保每个角色都有一个收集文档和权限


    第4部分:验证器中间件

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

    一,。使用AUTH url(registeredUrls.js)和超级管理员特定url(confgUrls.js)以及不同[simple_url]中的简单url在[AUTH_url]中填充所有需要验证的url

    二,。然后检查(AUTH_url.indexOf(request.url)>-1){3rd step}如果(SIMPLE_url.indexOf(request.url)>-1){那么它是公共url,所以SIMPLE allow next()}否则{响应未知url}

    三,。在这一步中,我们知道AUTH_url中请求的url因此需要对授权令牌头进行令牌检查,如果找到,则从中提取令牌,然后{4th step}