使用 Redis 实现 RBAC 权限管理
1. 什么是 RBAC?
RBAC(Role-Based Access Control,基于角色的访问控制)是一种常见的权限管理模型,它通过用户(User)、角色(Role)、权限(Permission) 及其映射关系来控制访问权限。RBAC 的基本思路是:
- 用户被分配一个或多个角色;
- 每个角色拥有一定的权限;
- 通过用户所属角色来决定其是否有权限访问某个资源。
2. 为什么使用 Redis 实现 RBAC?
在传统的 RBAC 设计中,权限数据通常存储在 数据库(如 MySQL),但这种方式可能存在以下问题:
- 查询性能低:每次鉴权都需要查询多张表,影响 API 响应速度;
- 不适用于高并发:数据库连接池有限,在高并发场景下可能成为瓶颈;
- 权限变更不灵活:数据库方案通常需要定期同步缓存,否则变更不会立即生效。
使用 Redis 作为 RBAC 权限存储的优势:
- 高性能:Redis 作为内存数据库,查询速度极快;
- 低延迟:可以直接
O(1)查询权限数据,而无需复杂的 SQL 语句; - 支持动态权限变更:用户权限变更可以实时生效,而不需要等待数据库更新;
- 适用于分布式系统:多台服务器可以共享 Redis 权限数据,避免不同实例状态不一致的问题。
3. 设计 RBAC 数据结构
我们使用 Redis 作为权限存储,并设计以下 Key 结构:
| Key | Value | 说明 |
|---|---|---|
user_roles:{user_id} | ["admin", "editor"] | 用户的角色列表 |
role_permissions:{role} | ["read", "write", "delete"] | 角色的权限列表 |
permission_routes:{permission} | ["GET:/users", "POST:/articles"] | 权限对应的 API |
blacklist_tokens | 存储已注销的 Token | 使 JWT 失效,支持主动登出 |
4. 代码实现
我们使用 Gin 作为 Web 框架,并结合 Redis 进行权限管理。
📌 4.1 安装依赖
go get -u github.com/gin-gonic/gin
go get -u github.com/golang-jwt/jwt/v5
go get -u github.com/redis/go-redis/v9
📌 4.2 初始化 Redis
package mainimport ("context""fmt""log""github.com/redis/go-redis/v9"
)// 初始化 Redis 客户端
var ctx = context.Background()
var redisClient = redis.NewClient(&redis.Options{Addr: "127.0.0.1:6379", // 连接 Redis
})// 初始化 RBAC 角色 & 权限映射
func setupRBAC() {// 角色 → 权限redisClient.SAdd(ctx, "role_permissions:admin", "read", "write", "delete")redisClient.SAdd(ctx, "role_permissions:editor", "read", "write")redisClient.SAdd(ctx, "role_permissions:viewer", "read")// 权限 → APIredisClient.SAdd(ctx, "permission_routes:read", "GET:/users", "GET:/articles")redisClient.SAdd(ctx, "permission_routes:write", "POST:/articles", "PUT:/articles")redisClient.SAdd(ctx, "permission_routes:delete", "DELETE:/articles")// 用户 → 角色redisClient.SAdd(ctx, "user_roles:1", "admin")redisClient.SAdd(ctx, "user_roles:2", "editor")redisClient.SAdd(ctx, "user_roles:3", "viewer")log.Println("RBAC 权限映射初始化完成")
}
📌 4.3 生成 JWT 令牌
package mainimport ("fmt""time""github.com/golang-jwt/jwt/v5"
)// JWT 密钥
var jwtSecret = []byte("supersecretkey")// 生成 JWT 令牌
func GenerateJWT(userID int) (string, error) {token := jwt.NewWithClaims(jwt.SigningMethodHS256, jwt.MapClaims{"user_id": userID,"exp": time.Now().Add(24 * time.Hour).Unix(), // 24 小时有效})return token.SignedString(jwtSecret)
}// 解析 JWT 令牌
func ParseJWT(tokenString string) (int, error) {token, err := jwt.Parse(tokenString, func(token *jwt.Token) (interface{}, error) {return jwtSecret, nil})if err != nil || !token.Valid {return 0, fmt.Errorf("invalid token")}claims, ok := token.Claims.(jwt.MapClaims)if !ok {return 0, fmt.Errorf("invalid claims")}return int(claims["user_id"].(float64)), nil
}
📌 4.4 鉴权中间件
// 访问权限检查
func hasAccess(userID int, method, path string) bool {// 1. 获取用户角色roles, err := redisClient.SMembers(ctx, fmt.Sprintf("user_roles:%d", userID)).Result()if err != nil || len(roles) == 0 {return false}// 2. 遍历角色,获取权限for _, role := range roles {permissions, _ := redisClient.SMembers(ctx, fmt.Sprintf("role_permissions:%s", role)).Result()for _, permission := range permissions {routes, _ := redisClient.SMembers(ctx, fmt.Sprintf("permission_routes:%s", permission)).Result()for _, route := range routes {if route == fmt.Sprintf("%s:%s", method, path) {return true}}}}return false
}// RBAC 中间件
func RBACMiddleware() gin.HandlerFunc {return func(c *gin.Context) {tokenString := c.GetHeader("Authorization")if tokenString == "" {c.JSON(401, gin.H{"error": "未提供 Token"})c.Abort()return}// 解析 JWTuserID, err := ParseJWT(tokenString)if err != nil {c.JSON(401, gin.H{"error": "Token 无效"})c.Abort()return}// 检查权限if !hasAccess(userID, c.Request.Method, c.FullPath()) {c.JSON(403, gin.H{"error": "无访问权限"})c.Abort()return}c.Set("userID", userID)c.Next()}
}
📌 4.5 API 接口
func main() {r := gin.Default()setupRBAC()// 登录r.POST("/login", func(c *gin.Context) {userID := 1 // 假设用户 1 登录token, _ := GenerateJWT(userID)c.JSON(200, gin.H{"token": token})})// 受保护 APIapi := r.Group("/api", RBACMiddleware())api.GET("/users", func(c *gin.Context) {c.JSON(200, gin.H{"message": "获取用户列表"})})api.POST("/articles", func(c *gin.Context) {c.JSON(200, gin.H{"message": "创建文章"})})api.DELETE("/articles", func(c *gin.Context) {c.JSON(200, gin.H{"message": "删除文章"})})r.Run(":8080")
}
5. 方案总结
✅ Redis 存权限(推荐):高效、适用于分布式
✅ RBAC 权限映射:角色权限映射清晰
✅ JWT 认证:无状态,适用于 API 认证
这样,你就能 用 Redis 设计一套高效的 RBAC 权限管理,并支持 API 映射!🔥
相关文章:
使用 Redis 实现 RBAC 权限管理
1. 什么是 RBAC? RBAC(Role-Based Access Control,基于角色的访问控制)是一种常见的权限管理模型,它通过用户(User)、角色(Role)、权限(Permissionÿ…...
正则表达式–断言
原文地址:正则表达式–断言 – 无敌牛 欢迎参观我的个人博客:正则表达式特殊字符 – 无敌牛 断言assertions 1、(?...):正向预查(positive lookahead),表示某个字符串后面应该跟着什么。但这个字符串本身…...
Python常见面试题的详解14
1. 从变量 A 中匹配 JSON 字符串 在处理文本数据时,有时需要从变量里找出其中的 JSON 字符串。JSON 字符串一般以 { 或 [ 开头,以 } 或 ] 结尾,但简单的正则匹配可能不够严谨,所以还需用 json 模块进行验证。 要点 利用正则表达…...
电脑想安装 Windows 11 需要开启 TPM 2.0 怎么办?
尽管 TPM 2.0 已经内置在许多新电脑中,但很多人并不知道如何激活这一功能,甚至完全忽略了它的存在。其实,只需简单的几步操作,你就能开启这项强大的安全特性,为你的数字生活增添一层坚固的防护屏障。无论你是普通用户还…...
QT之改变鼠标样式
QT改变鼠标图片 资源路径如下 代码实现 QPixmap customCursorPixmap(":/images/mouse.png");QCursor customCursor(customCursorPixmap);QWidget::setCursor(customCursor); // 可以设置为整个窗口或特定控件QWidget::setCursor(); // 设置为透明光标,…...
Node IO操作
文章目录 Node IO操作概述流的基本类型可读流读取模式可读流状态创建可读流使用可读流暂停和恢复绑定可写流 可写流创建可写流使用可写流关闭流缓冲数据 可读可写流转换流 Node IO操作 概述 在 Node.js 中,I/O(输入/输出)操作是异步的&…...
零基础进阶人工智能——发展史、核心技术、前沿应用与未来展望
引言:从科幻走向现实,人工智能不再遥远 人工智能(AI),曾经是科幻小说和电影中遥不可及的未来科技,如今已悄然渗透到我们生活的方方面面。从智能家居的语音助手,到医疗诊断的辅助系统࿰…...
ue----git局域网内部署裸仓库,别的机器进行访问
最近由于经常迁移项目到另一台机器上进行部署更新一点就要整个迁移 弄得麻烦了 就在网上学了一下这个方式 首先我们在想要建立裸仓库的电脑上找到一个文件夹放置我们的裸仓库 在此点击鼠标右键选择 open git bash here 输入命令 创裸仓库 git init --bare gitTestName.git…...
三、tsp学习笔记——屏幕移植
泰山派-6寸猫屏转接板 - 立创开源硬件平台 泰山派樱猫的教程,屏资料链接: https://pan.baidu.com/s/1pNAKH33r7LtZG6EwHJ-HNA?pwdnsde 提取码: nsde (不要浪费时间下载,没有用,下载gitee上的) leefei/tspi-disp-6…...
vue3-05reactive定义对象类型的响应式数据(不能进行基本类型数据的响应式)
1.前言 reactive定义对象类型的响应式数据(不能进行基本类型数据的响应式) 2.实践 2.1语法 const 代理对象 reactive(源对象) 接收一个对象(或数组),返回一个代理对象 (Proxy的实例对象,简称proxy对象) <script> import { reactive } from &qu…...
PaddlePaddle的OCR模型转onnx-转rknn模型_笔记4
一、PaddlePaddle的OCR模型转onnx 1、首先建立一个新的虚拟环境 conda create -n ppocr python3.10 -y conda activate ppocr 2、进入paddlepaddle官网输入以下指令安装paddlepaddle GPU版本 (我的cuda版本是11.8,根据你电脑装合适版本) pip instal…...
DeepSeek与ChatGPT的对比分析
一 概述 1 DeepSeek DeepSeek是杭州深度求索(DeepSeek)官方推出的AI助手,免费体验与全球领先AI模型的互动交流。总参数达到6710亿的DeepSeek-V3大模型,多项性能指标对齐海外顶尖模型,用更快的速度、更加全面强…...
OpenAI Swarm 多智能体框架介绍
目录 一、什么是 Swarm ? 二、Swarn 使用方法 2.1 安装依赖 2.2 实例 本篇文章主要介绍下 OpenAI Swarm 多智能体框架。 一、什么是 Swarm ? Swarm 是 OpenAI 开源的一款多智能体框架,但 OpenAI 对 Swarm 的定位是教育性、实验性的框架&…...
华大MCU HC32F005端口GPIO控制失效问题
1. 问题来源:RS485通信时,且数据量大、持续运行一段时间后,发现RS485使能引脚没有得到释放,导致总线锁死,无法通信,影响到整个总线的设备。 2. 问题分析:1)经过测试和跟踪ÿ…...
Android今日头条的屏幕适配方案
今日头条的屏幕适配方案是一种基于动态调整设备密度(density)的适配方法,其核心原理是通过修改系统默认的屏幕密度参数,使得不同分辨率和尺寸的设备能够按照设计图的尺寸比例显示界面元素。以下是其核心原理与实现细节的总结&…...
抓包工具是什么?
抓包工具是一种用于捕获和分析网络数据包的软件或硬件设备。它可以帮助用户监控网络通信过程,查看网络中传输的数据内容、协议类型、源地址、目的地址等信息。以下是关于抓包工具的一些详细解释: 1. 主要功能 捕获数据包:抓包工具能够实时捕…...
微信小程序消息推送解密
package com.test.main.b2b;import org.apache.commons.codec.binary.Base64;import javax.crypto.Cipher; import javax.crypto.spec.IvParameterSpec; import javax.crypto.spec.SecretKeySpec; import java.util.Arrays;/*** author * version 1.0* description: 解谜微信小…...
【大模型系列篇】DeepSeek-R1如何通过强化学习有效提升大型语言模型的推理能力?
如何通过强化学习(RL)有效提升大型语言模型(LLM)的推理能力? 《DeepSeek-R1: Incentivizing Reasoning Capability in LLMs via Reinforcement Learning》由DeepSeek-AI团队撰写,主要介绍了他们开发的第一代…...
企业存储系统
一、概述 数字经济 人类通过大数据(数字化的知识与信息)的识别—选择—过滤—存储—使用,引导、实现资源的快速优化配置与再生,实现经济高质量发展的经济形态。 产业互联网推动发展 企业开始进行数字化转型,将传统…...
数据结构系列一:初识集合框架+复杂度
前言 数据结构——是相互之间存在一种或多种特定关系的数据元素的集合。数据结构是计算机专业的基础课程,但也是一门不太容易学好的课,它当中有很多费脑子的东西,之后在学习时,你若碰到了困惑或不解的地方 都是很正常的反应&…...
【AI】GitHub Copilot
GitHub Copilot 是一款由 GitHub 和 OpenAI 合作开发的 AI 编程助手,它可以在多种开发工具中使用。以下是 GitHub Copilot 支持的主要开发工具和平台: 1. Visual Studio Code (VS Code) 官方支持:GitHub Copilot 在 VS Code 中拥有最完整的集…...
Linux系统编程学习 NO.14——缓冲区的概念、模拟实现Cstdio库
用户缓冲区 先介绍一下关于用户缓冲区的周边知识。 fread和fwrite的返回值 谈一谈fread和fwrite的返回值,如果写入/读取文件成功,fread或fwrite的返回值指的是实际写入/读取的内存块数量(实际的nmemb的大小)。假如fwrite写入的size是5字节,…...
Linux性能监控工具汇总
文章目录 前言一、性能监控工具介绍1.概念介绍2.常用组合方式3.对比 二、sar工具1.sar安装2.sar工具参数3.sar工具使用示例3.1.每两秒采集一次cpu使用情况,总计采集2次,然后输出CPU使用情况的统计信息3.2.磁盘IO使用情况统计3.3.内存使用情况统计3.4.网卡流量使用情…...
某手sig3-ios算法 Chomper黑盒调用
Chomper-iOS界的Unidbg 最近在学习中发现一个Chomper框架,Chomper 是一个模拟执行iOS可执行文件的框架,类似于安卓端大名鼎鼎的Unidbg。 这篇文章使用Chomper模拟执行某手的sig3算法,初步熟悉该框架。这里只熟悉模拟执行步骤以及一些常见的…...
MySQL版本选择与安装
MySQL版本选择与安装 MySQL 5.5 优点: 稳定性:5.5版本是长期支持(LTS)版本,因此它非常稳定,被广泛部署在生产环境中。 兼容性:与旧版本的MySQL和各种应用程序有很好的兼容性。 缺点: 过时:…...
【飞行器原理学习】——1. 机翼及机翼参数
飞行器原理学习——1.机翼 一、 概述 飞机的各种机翼是飞机的控制面 通过铰链、钢索、液压等方式连接在机身上 操纵面运动时,会改变机翼的弧度和形状,使流经的空气发生偏转,从而影响空气动力的大小。使飞机围绕着3轴运动 二、机翼的操纵面…...
TS语言自定义脚手架
初始化 新建文件夹初始化命令 npm init -ytsc --initnpm i types/nodenpm i typescript# 处理别名npm i -D tsc-alias -y 表示选项都为yes 安装ts相关依赖 新建相关文件 bin 文件夹 src文件夹 commands 文件夹 (命令 utils 文件夹 (封装方法) index.t…...
lab4 CSAPP:Cachelab
写在前面 最简单的一集 实验室分为两个部分。在A部分中,实现一个缓存模拟器。在B部分中,编写一个矩阵针对高速缓存性能优化的转置功能。 感觉是比较经典的问题,之前在体系结构的课程中接触过,终于能通过lab实操一下了。 实验目…...
VScode C语言学习开发环境;运行提示“#Include错误,无法打开源文件stdio.h”
C/C环境配置 参考: VS Code 配置 C/C 编程运行环境(保姆级教程)_vscode配置c环境-CSDN博客 基本步骤 - 安装MinGW-W64,其包含 GCC 编译器:bin目录添加到环境变量;CMD 中输入gcc --version或where gcc验证…...
雷龙CS SD NAND(贴片式TF卡)测评体验
声明:非广告,为用户体验文章 前段时间偶然获得了雷龙出品的贴片式 TF 卡芯片及转接板,到手的是两片贴片式 nand 芯片搭配一个转接板,其中有一片官方已经焊接好了,从外观来看,正面和背面设计布局合理&#x…...
