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)。
在实际应用中的作用是:-
-
Wanderer(刚刚访问我们网站的人。他应该能够访问所有公共路线。所有人都可以访问的简单网址/公共网址因此不需要为此设置单独的角色,因为它不是任何经过验证的权利。)
-
访客(已注册但未验证的人说电子邮件未验证)。
-
用户(拥有经过验证的电子邮件的人)
-
管理员(超级管理员验证后成为管理员。他享有大部分权利)
-
超级管理员(应用大师。他享有一些更高级的权限。更多权限然后管理员)
到目前为止,我们已经了解什么是正确的,以及它是如何映射到角色的。
第 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 中遵循程序:
- 将所有简单的 urls(public) 和 Auth Urls(admin & users) & super-admin-specific urls 加载到 superAdminRights[]。
- 如果不存在,则运行一个函数来创建一个角色为 superadmin 的用户。
- 如果找到,获取类型为:“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 { 响应“拒绝访问”}