主页 > 开源代码  > 

使用Redis实现RBAC权限管理

使用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 结构:

KeyValue说明user_roles:{user_id}["admin", "editor"]用户的角色列表role_permissions:{role}["read", "write", "delete"]角色的权限列表permission_routes:{permission}["GET:/users", "POST:/articles"]权限对应的 APIblacklist_tokens存储已注销的 Token使 JWT 失效,支持主动登出
4. 代码实现

我们使用 Gin 作为 Web 框架,并结合 Redis 进行权限管理。

📌 4.1 安装依赖 go get -u github /gin-gonic/gin go get -u github /golang-jwt/jwt/v5 go get -u github /redis/go-redis/v9

📌 4.2 初始化 Redis

package main import ( "context" "fmt" "log" "github /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") // 权限 → API redisClient.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 main import ( "fmt" "time" "github /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 } // 解析 JWT userID, 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}) }) // 受保护 API api := 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权限管理由讯客互联开源代码栏目发布,感谢您对讯客互联的认可,以及对我们原创作品以及文章的青睐,非常欢迎各位朋友分享到个人网站或者朋友圈,但转载请说明文章出处“使用Redis实现RBAC权限管理