发布于 2026-01-06 0 阅读
0

Node.js 用户角色和权限管理入门指南

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 
Enter fullscreen mode Exit fullscreen mode

这是为了安装必要的依赖项。我们还需要安装 nodemon。运行以下命令:

npm install nodemon
Enter fullscreen mode Exit fullscreen mode

之后,运行以下命令启动开发服务器:

npm run dev
Enter fullscreen mode Exit fullscreen mode

为了发起 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");
Enter fullscreen mode Exit fullscreen mode

现在我们可以继续学习本教程了。

那么,我们先从最基本的身份验证开始,也就是检查用户是否已登录。你需要编写一个中间件,它接收用户参数,检查用户是否存在,如果存在则继续执行,否则发送错误信息。

在 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();
}
Enter fullscreen mode Exit fullscreen mode

我们创建了一个名为中间件的函数authUser(),,它接收请求、响应和下一步操作。该函数会检查用户是否存在以及是否已登录。如果用户存在,则继续执行;否则,将报错。

请前往server.js并添加authUser到我们的仪表盘路由中。就像这样:

app.get("/dashboard", authUser, (req, res) => {
 res.send("Dashboard Page");
});
Enter fullscreen mode Exit fullscreen mode

通过发送请求进行测试。如果您发送的请求参数为userId1,您会注意到会收到一个响应,该响应会将您带到仪表板:

仪表板身份验证

如果没有用户,它会提示您登录:

用户必须登录才能访问仪表板

现在,您有了一个基本的身份验证形式,即只有登录用户才能访问仪表板,只有主页对所有人开放。

下一种身份验证方式是针对您的管理员页面,因为此页面应该只有管理员才能访问。但目前,每个用户和未登录用户都可以访问它。

首先,你需要检查是否存在用户,以及该用户是否为管理员,以便他们可以访问管理页面。在你的配置文件中server.js,将 `admin` 路由添加authUser到你的管理页面路由中。现在它看起来会像这样:

app.get("/admin", authUser,(req, res) => {
 res.send("Admin Page");
});
module.exports = { authUser };
Enter fullscreen mode Exit fullscreen mode

要对特定角色进行身份验证,您需要在代码中编写一些代码basicAuth来实现这一点。因此,在您的代码中basicAuth.js,创建一个函数,该函数接受您要进行身份验证的角色作为参数,并且在该函数内部,我们需要返回一个中间件,即 `<middleware_name>`、`<middleware_name>`reqres` <middleware_name> next`:

function authRole(role) {
 return (req, res, next) => {
   if (req.user.role !== role) {
     res.status(401);
     return res.send("not allowed");
   }
   next();
 };
Enter fullscreen mode Exit fullscreen mode

上面的代码中,我们有一个中间件函数,用于检查发出请求的用户的角色。该中间件接受三个参数:(req请求)、res(响应)和next(将控制权传递给下一个中间件或路由处理程序的函数)。

如果用户的角色与指定的角色不匹配,中间件会将HTTP状态码设置为401“未授权”,并返回“不允许”的响应。这样可以根据用户角色限制对某些路由或操作的访问。别忘了还要导出以下内容Authrole

module.exports = { authUser, authRole };
Enter fullscreen mode Exit fullscreen mode

server.js请记住,在本教程开始之前,我们已经导入了所有需要的内容。因此,在您的项目中server.js,将函数添加到管理路由,如下所示:

app.get("/admin", authUser, authRole(ROLE.ADMIN), (req, res) => {
 res.send("Admin Page");
});
Enter fullscreen mode Exit fullscreen mode

首先,路由会进行用户身份验证,确保用户已登录。然后,它会检查已验证的用户是否具有管理员角色。如果这两个条件都满足,则路由处理程序运行,并允许用户访问“管理页面”。否则,用户将被拒绝访问。

为了user 1

管理员仅拥有数据库访问权限

为了user 2 or 3

用户 2 未通过身份验证

你会注意到现在只有管理员才能访问该路由。这应该可以满足大部分身份验证需求,但对于特定路由(例如任务路由),你需要进行更具体的配置。

请注意,在数据中,除管理员外,每个用户都关联到一个特定的任务。管理员可以访问所有用户的任务。因此,您需要设置正确的身份验证机制,以防止任何用户访问未关联的任务。

创建一个名为 `<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,
};
Enter fullscreen mode Exit fullscreen mode

上面的代码中,该canViewTask函数检查给定用户是否拥有查看特定任务的权限。它会返回true用户的角色是否为“管理员”,或者任务的用户是否与该用户的 ID 匹配(如果该用户是任务的参与者)。简而言之,只有管理员ROLE.ADMIN才能查看任何任务,而普通用户只能查看自己的任务。

在我们的系统中tasks.js,我们需要设置身份验证。为此,首先需要验证用户是否存在,因为只有登录用户才能访问此页面。让我们将该userAuth函数导入到我们的系统中task.js

const { authUser } = require("../basicAuth");
Enter fullscreen mode Exit fullscreen mode

然后我们将其添加到任务路由中:

router.get("/:taskId", setTask, authUser, authGetTask, (req, res) => {
 res.json(req.task);
});
Enter fullscreen mode Exit fullscreen mode

注意问号了吗authGetTask?别担心,我们稍后会创建它。你需要为不同的权限添加身份验证canviewTask

const {canViewTask,} = require("../permissions/taskPermission");
Enter fullscreen mode Exit fullscreen mode

现在我们来创建这个authGetTask函数:

function authGetTask(req, res, next) {
 if (!canViewTask(req.user, req.task)) {
   res.status(401);
   return res.send("not allowed ");
 }
 next();
}
Enter fullscreen mode Exit fullscreen mode

上面的代码是一个中间件,它通过调用canViewTask函数来检查用户是否有权查看特定任务。如果用户没有权限,它会发送状态码为 0 的“不允许”响应401。否则,请求可以继续执行到下一个中​​间件或路由处理程序。

我们来测试一下身份验证是否有效。

你会看到,user 3当我们使用它来访问一个未与其关联的任务时,会显示“不允许”:

用户 3 无权查看任务

user 2并且user 1可以访问它,因为user 2它与它关联,而用户 1 是管理员:

用户 2 可以查看与其关联的任务。

用户 1 可以查看任务,因为他是管理员。

接下来我们要处理的是任务路由。它会返回所有任务,但现在所有用户都能同时看到所有任务,这不应该发生。

只有管​​理员才能看到完整的任务列表,而用户只能查看自己的任务列表,因此我们需要在任务中创建另一个函数permissions.js来处理用户实际可以查看哪些任务。

那么,让我们创建一个名为scopedProjects这样的函数:

function scopedTasks(user, tasks) {
 if (user.role === ROLE.ADMIN) return tasks;
 return tasks.filter((task) => task.userId === user.id);
}
Enter fullscreen mode Exit fullscreen mode

上述代码根据用户的角色筛选并返回任务子集。这是一个基于角色的访问控制系统示例,它会检查用户的角色是否为“管理员”。如果用户是管理员,则该函数返回未经筛选的原始任务数组(tasks)。

如果用户不是管理员,则使用筛选方法创建一个新数组,其中仅包含 userId 属性与用户匹配的任务ID

我们module.exports现在的界面是这样的:

module.exports = {
 canViewTask,
 scopedTasks,
};
Enter fullscreen mode Exit fullscreen mode

在内部task.js,让我们把第一条路线改成这样:

router.get("/", authUser, (req, res) => {
 res.json(scopedTasks(req.user, tasks));
});
Enter fullscreen mode Exit fullscreen mode

在上面的代码中,我们首先确保只有经过身份验证的用户才能访问后续路由。然后,我们传递所有任务的列表以及特定用户,将项目列表的范围限定到该特定用户。让我们来测试一下:

用户1可以查看所有任务

用户 2 只能查看与其关联的任务。

用户 3 只能查看与其关联的任务。

我们可以看到,管理员(用户 1)会显示所有任务,user 2以及与其关联的任务,以此类推user 3。现在,该系统正在处理我们路由的列表和权限。

好了,就到这里啦!如果需要的话,你们还可以添加删除和创建任务的路由。

结论

在 Node.js 中管理用户角色对于维护安全有序的 Web 应用程序至关重要。通过实施基于角色的访问控制、与数据库集成以及使用中间件进行身份验证和授权,您可以建立一个强大的系统,保护敏感数据并确保流畅的用户体验。

随时了解最佳实践和安全更新,以确保您的应用程序安全且保持最新状态。

文章来源:https://dev.to/oyedeletemitope/beginners-guide-to-managing-user-roles-and-pemissions-4glc