Node.js 用户角色和权限管理入门指南
随着应用程序的增长,管理用户角色对于确保适当的访问控制和安全性变得越来越重要。本文将探讨如何在 Node.js 应用程序中管理用户角色和权限。
了解用户角色
在深入技术实现之前,了解用户角色及其必要性非常重要。
用户角色定义了用户在应用程序中拥有的一组权限。例如,在博客平台中,拥有该author角色的用户可以创建和编辑自己的文章,但不能发布。
拥有特定角色的用户editor可以创建、编辑和发布帖子,但不能删除帖子。拥有完全admin控制权的用户可以完全控制应用程序的所有方面,包括管理用户和角色。
基于角色的访问控制(RBAC)
基于角色的访问控制 (RBAC),也称为基于角色的安全,是一种访问控制方法,它根据用户在组织中的角色为其分配权限。与单独分配权限相比,它提供了一种更易于管理、更不容易出错的访问管理方法。
基于角色的访问控制(RBAC)确保用户只能访问与其工作相关的必要信息并执行必要操作。这一概念被称为最小权限原则。
RBAC 的工作原理
RBAC 的工作原理非常简单。它将角色与特定权限关联起来,然后将这些角色分配给用户。
例如,假设你的应用程序中有诸如“管理员”administrator, manager,或“用户”之类的角色employee,每个角色都有不同的权限。当用户被分配到这些角色中的任何一个时,他们就会获得该角色所附带的权限。
如何在Node.js中实现用户角色
让我们通过一个例子来看看如何实现和管理用户角色。首先,我会提供一段基本的样板代码,你可以从GitHub获取这段代码,以便跟随本教程进行操作。接下来,我将解释以下文件:
-
Data.js:它将取代数据库。它包含了我们系统中所有不同的权限角色。任务也是如此,每个用户都有自己的任务。
-
Server.js:这里我们启动了一个 Express 服务器,导入了所有必需的依赖项和文件,并指示它使用 JSON 格式,以便我们可以从 POST 请求中获取数据。它还包含一些基本路由,例如,用于访问主页的 GET 路由、仪表盘路由等等。
最后,我们还有中间件,它负责设置用户。
routes/tasks.js:包含路由,即获取所有任务的路由、单个任务的路由,以及另一个指向我们获取路由的任务的路由。
克隆仓库后,运行:
npm i
这是为了安装必要的依赖项。我们还需要安装 nodemon。运行以下命令:
npm install nodemon
之后,运行以下命令启动开发服务器:
npm run dev
为了发起 API 请求,我将使用VS Code 中的REST 客户端。您也可以使用 Postman、Thunderclient 或任何您喜欢的工具。要使用 REST 客户端,请从 VS Code 扩展市场安装。
test.rest安装完成后,创建一个名为“用于测试我们的路由”的文件。
现在,你的系统有不同的路由,但这些路由都没有受到保护,也就是说,任何人都可以访问首页,管理页面也同样可以访问。如果你发送一个请求,你会发现即使你没有登录,你仍然可以访问管理页面。
您需要确保根据角色、他们可以访问的任务以及用户是否已登录来锁定这些不同的页面。
在开始之前,让我们先把需要的所有文件导入到我们的目录中,这样在教程过程中,server.js.您每次想继续操作时就不用再重新导入它们了:server.js
const { ROLE, users } = require("./data");
const { authUser, authRole } = require("./basicAuth");
现在我们可以继续学习本教程了。
那么,我们先从最基本的身份验证开始,也就是检查用户是否已登录。你需要编写一个中间件,它接收用户参数,检查用户是否存在,如果存在则继续执行,否则发送错误信息。
在 routes 文件夹内,创建一个名为 . 的文件basicAuth.js。这将用于基本身份验证。
创建一个名为 `function` 的函数,名称authUser()如下:
function authUser(req, res, next) {
if (req.user == null) {
res.status(403);
return res.send("you need to sign in ");
}
next();
}
我们创建了一个名为中间件的函数authUser(),,它接收请求、响应和下一步操作。该函数会检查用户是否存在以及是否已登录。如果用户存在,则继续执行;否则,将报错。
请前往server.js并添加authUser到我们的仪表盘路由中。就像这样:
app.get("/dashboard", authUser, (req, res) => {
res.send("Dashboard Page");
});
通过发送请求进行测试。如果您发送的请求参数为userId1,您会注意到会收到一个响应,该响应会将您带到仪表板:
如果没有用户,它会提示您登录:
现在,您有了一个基本的身份验证形式,即只有登录用户才能访问仪表板,只有主页对所有人开放。
下一种身份验证方式是针对您的管理员页面,因为此页面应该只有管理员才能访问。但目前,每个用户和未登录用户都可以访问它。
首先,你需要检查是否存在用户,以及该用户是否为管理员,以便他们可以访问管理页面。在你的配置文件中server.js,将 `admin` 路由添加authUser到你的管理页面路由中。现在它看起来会像这样:
app.get("/admin", authUser,(req, res) => {
res.send("Admin Page");
});
module.exports = { authUser };
要对特定角色进行身份验证,您需要在代码中编写一些代码basicAuth来实现这一点。因此,在您的代码中basicAuth.js,创建一个函数,该函数接受您要进行身份验证的角色作为参数,并且在该函数内部,我们需要返回一个中间件,即 `<middleware_name>`、`<middleware_name>`req和res` <middleware_name> next`:
function authRole(role) {
return (req, res, next) => {
if (req.user.role !== role) {
res.status(401);
return res.send("not allowed");
}
next();
};
上面的代码中,我们有一个中间件函数,用于检查发出请求的用户的角色。该中间件接受三个参数:(req请求)、res(响应)和next(将控制权传递给下一个中间件或路由处理程序的函数)。
如果用户的角色与指定的角色不匹配,中间件会将HTTP状态码设置为401“未授权”,并返回“不允许”的响应。这样可以根据用户角色限制对某些路由或操作的访问。别忘了还要导出以下内容Authrole:
module.exports = { authUser, authRole };
server.js请记住,在本教程开始之前,我们已经导入了所有需要的内容。因此,在您的项目中server.js,将函数添加到管理路由,如下所示:
app.get("/admin", authUser, authRole(ROLE.ADMIN), (req, res) => {
res.send("Admin Page");
});
首先,路由会进行用户身份验证,确保用户已登录。然后,它会检查已验证的用户是否具有管理员角色。如果这两个条件都满足,则路由处理程序运行,并允许用户访问“管理页面”。否则,用户将被拒绝访问。
为了user 1:
为了user 2 or 3:
你会注意到现在只有管理员才能访问该路由。这应该可以满足大部分身份验证需求,但对于特定路由(例如任务路由),你需要进行更具体的配置。
请注意,在数据中,除管理员外,每个用户都关联到一个特定的任务。管理员可以访问所有用户的任务。因此,您需要设置正确的身份验证机制,以防止任何用户访问未关联的任务。
创建一个名为 `<routes_name>` 的新文件夹permissions。我们将在这里为特定路由创建权限。在该文件夹内,创建一个名为 `<routes_name>` 的新文件tasks.js。首先,我们将创建一个函数来检查用户是否有权访问某个任务:
const { ROLE } = require("../data");
function canViewTask(user, task) {
return user.role === ROLE.ADMIN || task.userId == user.id;
}
module.exports = {
canViewTask,
};
上面的代码中,该canViewTask函数检查给定用户是否拥有查看特定任务的权限。它会返回true用户的角色是否为“管理员”,或者任务的用户是否与该用户的 ID 匹配(如果该用户是任务的参与者)。简而言之,只有管理员ROLE.ADMIN才能查看任何任务,而普通用户只能查看自己的任务。
在我们的系统中tasks.js,我们需要设置身份验证。为此,首先需要验证用户是否存在,因为只有登录用户才能访问此页面。让我们将该userAuth函数导入到我们的系统中task.js:
const { authUser } = require("../basicAuth");
然后我们将其添加到任务路由中:
router.get("/:taskId", setTask, authUser, authGetTask, (req, res) => {
res.json(req.task);
});
注意问号了吗authGetTask?别担心,我们稍后会创建它。你需要为不同的权限添加身份验证canviewTask:
const {canViewTask,} = require("../permissions/taskPermission");
现在我们来创建这个authGetTask函数:
function authGetTask(req, res, next) {
if (!canViewTask(req.user, req.task)) {
res.status(401);
return res.send("not allowed ");
}
next();
}
上面的代码是一个中间件,它通过调用canViewTask函数来检查用户是否有权查看特定任务。如果用户没有权限,它会发送状态码为 0 的“不允许”响应401。否则,请求可以继续执行到下一个中间件或路由处理程序。
我们来测试一下身份验证是否有效。
你会看到,user 3当我们使用它来访问一个未与其关联的任务时,会显示“不允许”:
user 2并且user 1可以访问它,因为user 2它与它关联,而用户 1 是管理员:
接下来我们要处理的是任务路由。它会返回所有任务,但现在所有用户都能同时看到所有任务,这不应该发生。
只有管理员才能看到完整的任务列表,而用户只能查看自己的任务列表,因此我们需要在任务中创建另一个函数permissions.js来处理用户实际可以查看哪些任务。
那么,让我们创建一个名为scopedProjects这样的函数:
function scopedTasks(user, tasks) {
if (user.role === ROLE.ADMIN) return tasks;
return tasks.filter((task) => task.userId === user.id);
}
上述代码根据用户的角色筛选并返回任务子集。这是一个基于角色的访问控制系统示例,它会检查用户的角色是否为“管理员”。如果用户是管理员,则该函数返回未经筛选的原始任务数组(tasks)。
如果用户不是管理员,则使用筛选方法创建一个新数组,其中仅包含 userId 属性与用户匹配的任务ID。
我们module.exports现在的界面是这样的:
module.exports = {
canViewTask,
scopedTasks,
};
在内部task.js,让我们把第一条路线改成这样:
router.get("/", authUser, (req, res) => {
res.json(scopedTasks(req.user, tasks));
});
在上面的代码中,我们首先确保只有经过身份验证的用户才能访问后续路由。然后,我们传递所有任务的列表以及特定用户,将项目列表的范围限定到该特定用户。让我们来测试一下:
我们可以看到,管理员(用户 1)会显示所有任务,user 2以及与其关联的任务,以此类推user 3。现在,该系统正在处理我们路由的列表和权限。
好了,就到这里啦!如果需要的话,你们还可以添加删除和创建任务的路由。
结论
在 Node.js 中管理用户角色对于维护安全有序的 Web 应用程序至关重要。通过实施基于角色的访问控制、与数据库集成以及使用中间件进行身份验证和授权,您可以建立一个强大的系统,保护敏感数据并确保流畅的用户体验。
随时了解最佳实践和安全更新,以确保您的应用程序安全且保持最新状态。
文章来源:https://dev.to/oyedeletemitope/beginners-guide-to-managing-user-roles-and-pemissions-4glc









