在 Node.js 中实现基于角色的访问控制

在 Node.js 中实现基于角色的访问控制

基于角色的访问控制 (Role-Based Access Control,缩写RBAC) 是应用程序安全性的一个重要方面。它提供了一种结构化方法,可以根据组织或应用程序中用户的角色来管理和限制对资源的访问。在本文中,我们将探讨 RBAC 的概念,讨论其优点,并引导完成在 Node.js 中实现 RBAC 的过程。

基于角色的访问控制简介

什么是 RBAC?

RBAC是一种将系统访问限制为授权用户的安全概念。在 RBAC 中,访问权限与角色相关联,用户被分配一个或多个角色。这些角色定义用户可以在系统中执行哪些操作或操作。

RBAC 通过集中权限来简化访问控制,使管理员能够在较高级别管理用户访问。它通过确保用户仅拥有执行其角色所需的权限来增强安全性,从而降低未经授权的操作的风险。

RBAC 的好处

RBAC 具有许多好处,包括:

  • 安全性:RBAC 能最大限度地降低应用程序内未经授权的访问或操作的风险,从而减少安全漏洞。
  • 简单性:它通过将权限分组到角色来简化用户访问管理,使管理更加简单。
  • 可扩展性:RBAC 具有高度可扩展性,使其适用于小型和大型应用程序。
  • 合规性:许多监管框架(例如 GDPRHIPAA)需要强大的访问控制机制。
  • 可审核性:RBAC 允许我们跟踪和审核用户操作,这对于识别安全漏洞至关重要。

项目结构

这是我们将在本教程中使用的基本项目结构:

my-rbac-app/
│
├── package.json
├── package-lock.json
├── index.js
├── models/
│   └── user.js
├── routes/
│   └── auth.js
│   └── tasks.js
├── controllers/
│   └── authController.js
│   └── tasksController.js
├── middleware/
│   └── rbacMiddleware.js
│
└── config/└── roles.json

用户角色和权限

定义角色和权限

RBAC 中,角色代表组织内的工作职能或头衔,权限是可以执行的操作或操作。让我们首先为我们的项目定义一些角色和权限。

在目录中创建一个roles.json文件:

{"roles": [{"name": "admin","permissions": ["create_task","read_task","update_task","delete_task"]},{"name": "manager","permissions": ["create_task","read_task","update_task"]},{"name": "employee","permissions": ["create_task","read_task"]}]
}

在这里,我们定义了三个角色:“管理员”、“经理”和“员工”,每个角色都具有与任务管理相关的不同权限集。

存储角色和权限数据

现在,让我们创建模型来表示角色和权限。在models/目录中,创建一个role.js文件:

// models/role.jsconst roles = require('../config/roles.json');class Role {constructor() {this.roles = roles.roles;}getRoleByName(name) {return this.roles.find((role) => role.name === name);}getRoles() {return this.roles;}
}module.exports = Role;

在上面的代码中,我们创建了一个从文件中读取角色和权限的类Role。我们还提供按名称检索角色或获取所有角色列表的方法。

接下来,在同一目录中创建一个models/permissions.js文件:

// models/permissions.jsclass Permissions {constructor() {this.permissions = [];}getPermissionsByRoleName(roleName) {const role = roles.roles.find((r) => r.name === roleName);return role ? role.permissions : [];}
}module.exports = Permissions;

Permissions允许我们根据角色名称获取权限。在为用户分配角色并检查 RBAC 中间件中的权限时,我们将使用这些模型。

定义角色和权限并建立模型后,让我们继续进行用户身份验证。

用户认证

实施用户认证

用户身份验证是 RBAC 的基本组成部分。我们将使用passport库来处理身份验证。
首先,安装所需的依赖项:

npm install passport mongoose passport-local passport-local-mongoose express-session

现在,使用 MongoosePassport 创建用户模型models/user.js

// models/user.jsconst mongoose = require('mongoose');
const passportLocalMongoose = require('passport-local-mongoose');const userSchema = new mongoose.Schema({username: String,password: String,role: String,
});userSchema.plugin(passportLocalMongoose);const User = mongoose.model('User', userSchema);module.exports = User;

在上面的代码中,我们创建了一个包含必要字段的用户模型,并用passport-local-mongoose来实现用户身份验证。

角色分配

现在,当用户注册或创建时,我们需要为他们分配角色。

// controllers/authController.jsconst User = require('../models/user');
const Role = require('../models/role');// 注册用户
exports.registerUser = (req, res) => {const { username, password, role } = req.body;const user = new User({ username, role });User.register(user, password, (err) => {if (err) {console.error(err);return res.status(500).json({ error: err.message });}res.json({ message: '用户注册成功' });});
};

在上面的代码中,我们创建一个新用户并在注册期间指定其角色。用户的角色将根据应用程序的业务逻辑来定义。

完成用户身份验证和角色分配后,我们现在可以继续创建基于角色的中间件来保护路由。

基于角色的中间件

创建 RBAC 中间件

Node.js 中的中间件对于处理路由保护和用户授权等任务至关重要。我们将创建 RBAC 中间件来检查用户是否具有访问特定路由的必要权限。

// middleware/rbacMiddleware.jsconst Role = require('../models/role');
const Permissions = require('../models/permissions');// 判断用户是否存在访问权限
exports.checkPermission = (permission) => {return (req, res, next) => {const userRole = req.user ? req.user.role : 'anonymous';const userPermissions = new Permissions().getPermissionsByRoleName(userRole);if (userPermissions.includes(permission)) {return next();} else {return res.status(403).json({ error: 'Access denied' });}};
};

在此中间件中,我们从用户的会话中提取用户的角色,并检查该角色是否具有访问路由所需的权限。如果用户拥有必要的权限,则允许他们继续;否则,将发送403 Forbidden响应。

保护路由

要使用 RBAC 中间件保护特定路由,需要导入中间件函数并将其应用到路由处理程序中的所需路由。

// routes/tasks.jsconst express = require('express');
const router = express.Router();
const rbacMiddleware = require('../middleware/rbacMiddleware');// 引入控制器
const tasksController = require('../controllers/tasksController');// 使用中间件
router.get('/tasks', rbacMiddleware.checkPermission('read_task'), tasksController.getAllTasks);module.exports = router;

现在,tasks路由受到保护,只有具有read_task权限的用户才能访问它。

RBAC 中间件就位后,我们现在可以继续构建一个示例项目来查看 RBAC 的实际应用。

示例项目:RBAC 实际应用

在本节中,我们将使用 RBAC 构建一个简单的任务管理系统。我们将定义角色和权限,创建用户身份验证,为用户分配角色,并根据用户的角色和权限保护路由。

构建一个简单的任务管理系统

让我们首先定义任务管理系统的基本路由。创建一个新文件tasks.js

// routes/tasks.jsconst express = require('express');
const router = express.Router();
const rbacMiddleware = require('../middleware/rbacMiddleware');// 引入控制器
const tasksController = require('../controllers/tasksController');// 使用中间件
router.get('/tasks', rbacMiddleware.checkPermission('read_task'), tasksController.getAllTasks);
router.post('/tasks', rbacMiddleware.checkPermission('create_task'), tasksController.createTask);
router.put('/tasks/:id', rbacMiddleware.checkPermission('update_task'), tasksController.updateTask);
router.delete('/tasks/:id', rbacMiddleware.checkPermission('delete_task'), tasksController.deleteTask);module.exports = router;

在此代码中,我们定义了用于列出、创建、更新和删除任务的路由。每个路由都受到 RBAC 中间件的保护,该中间件在允许访问之前检查用户的权限。

定义角色和权限

在为用户分配角色之前,我们先定义应用程序的角色和权限。在config/roles.json文件中,指定角色及其关联的权限:

{"roles": [{"name": "admin","permissions": ["create_task", "read_task", "update_task", "delete_task"]},{"name": "manager","permissions": ["create_task", "read_task", "update_task"]},{"name": "employee","permissions": ["create_task", "read_task"]}]
}

我们定义了三个角色:“管理员”、“经理”和“员工”,每个角色都有不同的访问级别。

实施认证和授权

controllers/authController.js文件中,实现用户注册和登录功能:

// controllers/authController.jsconst User = require('../models/user');
const Role = require('../models/role');exports.registerUser = (req, res) => {const { username, password, role } = req.body;const user = new User({ username, role });User.register(user, password, (err) => {if (err) {console.error(err);return res.status(500).json({ error: err.message });}res.json({ message: 'User registered successfully' });});
};exports.loginUser = (req, res) => {const { username, password } = req.body;User.authenticate(username, password, (err, user) => {if (err || !user) {return res.status(401).json({ error: 'Invalid credentials' });}req.session.userId = user._id; res.json({ message: 'Login successful' });});
};
exports.logoutUser = (req, res) => {if (req.session) {req.session.destroy((err) => {if (err) {return res.status(500).json({ error: err.message });  }res.json({ message: 'Logged out successfully' });});} else {res.json({ message: 'Not logged in' });}
};

loginUserlogoutUser函数中,可以根据应用程序的需要实现登录和注销逻辑。

结论

在本文中,我们探讨了基于角色的访问控制 (RBAC) 的概念,并演示了如何在 Node.js 应用程序中实现它。我们介绍了角色和权限定义、用户身份验证、角色分配、基于角色的中间件,并创建了一个示例任务管理系统来展示 RBAC 的实际应用。

通过实施 RBAC,我们可以显着增强 Node.js 应用程序的安全性,有效控制用户访问,并降低安全漏洞的风险。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/116113.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

最详细STM32,cubeMX串口发送,接收数据

这篇文章将详细介绍 串口 发送数据,接受数据。 文章目录 前言一、串口的基础知识二、cubeMX 配置三、自动生成代码解析四、串口发送数据函数五、使用串口收发数据点亮 led重定向函数: 总结 前言 实验开发板:STM32F103C8T6。所需软件&#xf…

【TES605】基于Virtex-7 FPGA的高性能实时信号处理平台

板卡概述 TES605是一款基于Virtex-7 FPGA的高性能实时信号处理平台,该平台采用1片TI的KeyStone系列多核DSP TMS320C6678作为主处理单元,采用1片Xilinx的Virtex-7系列FPGA XC7VX690T作为协处理单元,具有2个FMC子卡接口,各个处理节…

景联文科技:针对敏感数据的安全转录服务,护航信息安全

针对数据的安全转录服务,主要是为了确保数据在转录过程中的安全性和隐私保护。这些服务通常会采用一系列严格的安全措施,如数据加密、访问控制、数据脱敏等,以确保敏感数据不会被泄露或滥用。 景联文科技提供特定的数据转录服务,以…

CentOS7.9+Kubernetes1.28.3+Docker24.0.6高可用集群二进制部署

CentOS7.9Kubernetes1.28.3Docker24.0.6高可用集群二进制部署 查看版本关系 ## 从kubernetes-server-linux-amd64.tar.gz解压后有kubeadm ]# ./kubeadm config images list W1022 20:06:05.647976 29233 version.go:104] could not fetch a Kubernetes version from the in…

WPF Material Design UI框架

前言 Material Design in xaml 是开源免费的ui框架&#xff0c;工控软件主打的就是简单界面。 以下简称MD 相关资源 MaterialDesignInXamlToolkit Github 地址 MD 快速启动 MD 案例压缩包 MD 框架使用 启动环境配置 安装Nuget包 App.xaml 配置 <Application x:Class&qu…

leetcode:面试题 17.04. 消失的数字(找单身狗/排序/公式)

一、题目&#xff1a; 函数原型&#xff1a;int missingNumber(int* nums, int numsSize) 二、思路&#xff1a; 思路1 利用“找单身狗”的思路&#xff08;n^n0&#xff1b;0^nn&#xff09;&#xff0c;数组中有0-n的数字&#xff0c;但缺失了一个数字x。将这些数字按位异或0…

zookeeper源码(02)源码编译启动及idea导入

本文介绍一下zookeeper-3.9.0源码下载、编译及本地启动。 下载源码 git clone https://gitee.com/apache/zookeeper.gitcd zookeeper git checkout release-3.9.0 git checkout -b release-3.9.0源码编译 README_packaging.md文件 该文件介绍了编译zookeeper需要的环境和命…

PKU 概率论+数理统计+建模 期中考复习总结

目录 计算条件概率计算概率&#xff08;放回与不放回&#xff09;生成随机数算法Linear Congruential Method判断是否是full period Uniformity (test of frequency)1.Chi-Square testmethodreminderexample 2.Kolmogorov-Sminov testmethodexample Independence (test of auto…

决策树-入门

1、认识决策树 决策树思想的来源非常朴素&#xff0c;程序设计中的条件分支结构就是if-then结构&#xff0c;最早的决策树就是利用这类结构分割数据的一种分类学习方法 怎么理解这句话&#xff1f;通过一个对话例子 想一想这个女生为什么把年龄放在最上面判断&#xff01;&a…

WebSocket—STOMP详解(官方原版)

WebSocket协议定义了两种类型的消息&#xff08;文本和二进制&#xff09;&#xff0c;但其内容未作定义。该协议定义了一种机制&#xff0c;供客户端和服务器协商在WebSocket之上使用的子协议&#xff08;即更高级别的消息传递协议&#xff09;&#xff0c;以定义各自可以发送…

【Java笔试强训】Day4(WY33 计算糖果、DD5 进制转换)

WY33 计算糖果 链接&#xff1a;WY33 计算糖果 题目&#xff1a; A,B,C三个人是好朋友,每个人手里都有一些糖果,我们不知道他们每个人手上具体有多少个糖果,但是我们知道以下的信息&#xff1a; A - B, B - C, A B, B C. 这四个数值.每个字母代表每个人所拥有的糖果数. 现…

Win10/Win11系统bitlocker正在等待激活如何解决?

有同学升级Win10系统后&#xff0c;发现C盘与D盘分区盘符中出现了黄色的锁定感叹号&#xff0c;还显示“bitlocker正在等待激活”&#xff0c;这可能是用户开启了bitlocker加密所导致的。下面就来看看解决的办法吧。 一、bitlocker正在等待激活的解决方法 打开控制面板-系统和安…

.obj模型文件(带材质和纹理)合并的基本思路

1、将v开头的顶点信息依次拷贝到合并新.obj中 2、将vt纹理坐标依次拷贝到合并新.obj中 3、f&#xff08;面&#xff09;的合并 步骤&#xff1a; &#xff08;1&#xff09;第一个obj文件的f&#xff08;面&#xff09;原封不动拷进新.obj中 &#xff08;2&#xff09;第二个…

【git 学习】--- ubuntu18.04 搭建本地git服务器

在Ubuntu18.04 上简单创建自己的git服务器~ 环境配置 Ubuntu: 18.04git服务器搭建步骤&#xff1a; ##1.安装git sudo apt-get install git##2.添加用户 sudo adduser test_git //test_git -- git用户名##3. 在Git用户的home目录下创建文件夹&#xff0c;作为裸仓库 sudo…

【虚幻引擎UE】UE4/UE5 基于2D屏幕坐标获取场景3D坐标 射线检测(蓝图/C++)

UE4/UE5 基于2D屏幕坐标获取场景3D坐标 一、射线检测1&#xff09;定义1&#xff09;射线与3D场景中的物体交互的流程2&#xff09;射线检测蓝图函数3&#xff09;蓝图实现根据鼠标点击位置获取场景中的坐标值4&#xff09;根据相机中心点获取场景中的坐标值5&#xff09;射线检…

MSQL系列(七) Mysql实战-SQL语句Join,exists,in的区别

Mysql实战-SQL语句Join&#xff0c;exists&#xff0c;in的区别 前面我们讲解了索引的存储结构&#xff0c;BTree的索引结构&#xff0c;以及索引最左侧匹配原则及讲解一下常用的SQL语句的优化建议&#xff0c;今天我们来详细讲解一下 我们经常使用的 join&#xff0c; exist&…

进程之操作系统的概念

再小的努力&#xff0c;乘以365都很明显。文章目录 操作系统操作系统的概念设计操作系统的目的 管理 ps:如何理解管理如何进行管理 操作系统管理软硬件资源小总结系统调用和库函数的概念小总结 操作系统 在讲述进程的时候我们先讲述一下操作系统&#xff08;os&#xff09;,因…

VR全景平台应该具备哪些功能,怎样选择VR全景平台

引言&#xff1a; 虚拟现实&#xff08;VR&#xff09;技术在不断发展&#xff0c;为企业和消费者提供了全新的交互体验。VR全景平台是一个关键的组成部分&#xff0c;它必须具备一系列重要的功能来吸引用户、提供内容和实现商业成功。那么VR全景平台应该具备哪些功能&#xf…

数据分析和机器学习的11个高级可视化图表介绍

可视化是一种强大的工具&#xff0c;用于以直观和可理解的方式传达复杂的数据模式和关系。它们在数据分析中发挥着至关重要的作用&#xff0c;提供了通常难以从原始数据或传统数字表示中辨别出来的见解。 可视化对于理解复杂的数据模式和关系至关重要&#xff0c;我们将介绍11…

面试题—JAVA基础①

文章目录 1.Java面向对象有哪些特征&#xff1f;2.ArrayList和LinkedList有什么区别&#xff1f;3.Java接口和抽象类有哪些区别&#xff1f;4.hashcode和equals如何使用&#xff1f;5.try-catch6.局部变量和实例变量7.String、StringBuffer、StringBuilder 的区别&#xff1f;8…