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

时间:2016-08-11 10:01:51

标签: node.js rest express

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

2 个答案:

答案 0 :(得分:17)

创建表格

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

  1. 创建角色表('管理员','用户','访客')
  2. 创建资源表('用户','项目','程序')
  3. 创建权限表('创建','读','写','删除','拒绝')
  4. 创建一个包含所有三个表作为来源的联结表
  5. 您可能不需要权限表的那种粒度,但有些人喜欢它。例如,您不需要'拒绝',因为您只需检查Read!= true。

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

    创建中间件

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

       public class MyClass : IValidatableObject
        {
            [Required(ErrorMessage="Please enter a Start Date")]  
            public DateTime? StartDate { get; set; }
    
            [Required(ErrorMessage="Please enter an End Date")]
            public DateTime? EndDate { get; set; }
    
            public IEnumerable<ValidationResult> Validate(ValidationContext context)
            {
                if (EndDate < StartDate)
                {
                    yield return new ValidationResult("Invalid date range: End date must be greater then the Start Date");
                }
            }
    }
    

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

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

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

答案 1 :(得分:3)

Node.js中的角色


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

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

权利是授予角色访问权限的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);

现在请记住,假定存在的每个角色都在Role集合中,并且具有上述架构类型。

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

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

因此,如果具有角色 user 的用户有权更改用户名,那么他可以访问url /users/set-username。但是,流浪者将无法访问此url。从逻辑上来说,像admin和superadmin之类的较高角色应该有权访问所有较低角色的权限(URL)。

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

  1. 流浪者刚刚访问我们网站的人。他应该能够访问所有公共路线。所有人都可以访问的简单网址/公共网址,因此无需为因为这不是经过身份验证的权利。
  2. 来宾已注册但未通过验证的人说电子邮件未通过验证)。
  3. 用户已验证电子邮件的人
  4. 管理员由SuperAdmin验证后成为管理员,他享有大部分权利
  5. 超级管理员应用程序大师。他享有一些更复杂的权限。然后是admin )。

直到现在我们已经了解了什么是正确的,以及如何将其映射到角色。


第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部分:创建SuperAdmin

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

  1. 将所有简单的url(公共)和Auth Urls(管理员和用户)以及特定于超级管理员的url加载到superAdminRights []中。
  2. 然后运行一个函数,以创建具有超级管理员角色的用户。
  3. 获取类型为“ superadmin”的角色:如果找到:用新权限(superAdminRights)替换其权限。else:创建类型为“ superadmin”的角色,然后填充其权限(superAdminRights)。

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


第3部分:特定于Super-Admin的网址

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

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

该过程确保每个角色都具有收款凭证并在其中具有填充权限。


第4部分:Authenticator中间件

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

1。

用auth-urls(registeredUrls.js)和super-admin-specific-urls(confgUrls.js)填充简单身份验证URL,并在不同的[SIMPLE_URLS]中填充简单身份验证URL。

2。然后检查是否(AUTH_URLS.indexOf(request.url)> -1){-1第三步},否则(SIMPLE_URLS.indexOf(request.url)>-1){那么这是公共网址,那么简单地允许next()}否则{响应未知网址}

3。在这一步中,我们知道在AUTH_URLS中请求的url要求对授权令牌头进行令牌检查(如果找到),然后从令牌中提取令牌。{第四步}。如果未找到授权头,则响应“必需令牌” /“未知”。

4。找到令牌,现在验证此令牌是否具有有效的会话。如果是,请{5th step}否则找不到令牌会话再次登录。 5。验证jwt令牌进行验证{6.step},否则返回“无效的jwt令牌”。

6。直到现在正确请求的url和令牌会话存在且jwt有效令牌。现在使用会话中的角色类型信息(存储在会话中是用户和令牌的基本信息)在此用户会话角色的角色中找到-type,因此我们拥有它的权限[]。现在,看看request.url是否包含在权限[]中。如果找到了{第七步}否则{响应“未找到角色/未知用户”}。

7。如果找到,则{可以访问此URL next()}否则{响应“访问被拒绝”}