最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

Redis實(shí)現(xiàn)RBAC權(quán)限管理

 更新時間:2025年03月10日 09:17:52   作者:nbsaas-boot  
本文主要介紹了Redis實(shí)現(xiàn)RBAC權(quán)限管理,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧

1. 什么是 RBAC?

RBAC(Role-Based Access Control,基于角色的訪問控制)是一種常見的權(quán)限管理模型,它通過用戶(User)、角色(Role)、權(quán)限(Permission) 及其映射關(guān)系來控制訪問權(quán)限。RBAC 的基本思路是:

  • 用戶被分配一個或多個角色;
  • 每個角色擁有一定的權(quán)限;
  • 通過用戶所屬角色來決定其是否有權(quán)限訪問某個資源。

2. 為什么使用 Redis 實(shí)現(xiàn) RBAC?

在傳統(tǒng)的 RBAC 設(shè)計(jì)中,權(quán)限數(shù)據(jù)通常存儲在 數(shù)據(jù)庫(如 MySQL),但這種方式可能存在以下問題:

  • 查詢性能低:每次鑒權(quán)都需要查詢多張表,影響 API 響應(yīng)速度;
  • 不適用于高并發(fā):數(shù)據(jù)庫連接池有限,在高并發(fā)場景下可能成為瓶頸;
  • 權(quán)限變更不靈活:數(shù)據(jù)庫方案通常需要定期同步緩存,否則變更不會立即生效。

使用 Redis 作為 RBAC 權(quán)限存儲的優(yōu)勢:

  • 高性能:Redis 作為內(nèi)存數(shù)據(jù)庫,查詢速度極快;
  • 低延遲:可以直接 O(1) 查詢權(quán)限數(shù)據(jù),而無需復(fù)雜的 SQL 語句;
  • 支持動態(tài)權(quán)限變更:用戶權(quán)限變更可以實(shí)時生效,而不需要等待數(shù)據(jù)庫更新;
  • 適用于分布式系統(tǒng):多臺服務(wù)器可以共享 Redis 權(quán)限數(shù)據(jù),避免不同實(shí)例狀態(tài)不一致的問題。

3. 設(shè)計(jì) RBAC 數(shù)據(jù)結(jié)構(gòu)

我們使用 Redis 作為權(quán)限存儲,并設(shè)計(jì)以下 Key 結(jié)構(gòu):

KeyValue說明
user_roles:{user_id}["admin", "editor"]用戶的角色列表
role_permissions:{role}["read", "write", "delete"]角色的權(quán)限列表
permission_routes:{permission}["GET:/users", "POST:/articles"]權(quán)限對應(yīng)的 API
blacklist_tokens存儲已注銷的 Token使 JWT 失效,支持主動登出

4. 代碼實(shí)現(xiàn)

我們使用 Gin 作為 Web 框架,并結(jié)合 Redis 進(jìn)行權(quán)限管理。

?? 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 main

import (
	"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 角色 & 權(quán)限映射
func setupRBAC() {
	// 角色 → 權(quán)限
	redisClient.SAdd(ctx, "role_permissions:admin", "read", "write", "delete")
	redisClient.SAdd(ctx, "role_permissions:editor", "read", "write")
	redisClient.SAdd(ctx, "role_permissions:viewer", "read")

	// 權(quán)限 → 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 權(quán)限映射初始化完成")
}

?? 4.3 生成 JWT 令牌

package main

import (
	"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 鑒權(quán)中間件

// 訪問權(quán)限檢查
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. 遍歷角色,獲取權(quán)限
	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
		}

		// 檢查權(quán)限
		if !hasAccess(userID, c.Request.Method, c.FullPath()) {
			c.JSON(403, gin.H{"error": "無訪問權(quán)限"})
			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 // 假設(shè)用戶 1 登錄
		token, _ := GenerateJWT(userID)
		c.JSON(200, gin.H{"token": token})
	})

	// 受保護(hù) 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": "創(chuàng)建文章"})
	})

	api.DELETE("/articles", func(c *gin.Context) {
		c.JSON(200, gin.H{"message": "刪除文章"})
	})

	r.Run(":8080")
}

5. 方案總結(jié)

? Redis 存權(quán)限(推薦):高效、適用于分布式
? RBAC 權(quán)限映射:角色權(quán)限映射清晰
? JWT 認(rèn)證:無狀態(tài),適用于 API 認(rèn)證

這樣,你就能 用 Redis 設(shè)計(jì)一套高效的 RBAC 權(quán)限管理,并支持 API 映射!

到此這篇關(guān)于Redis實(shí)現(xiàn)RBAC權(quán)限管理的文章就介紹到這了,更多相關(guān)Redis RBAC權(quán)限內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

  • Redis BloomFilter實(shí)例講解

    Redis BloomFilter實(shí)例講解

    這篇文章主要介紹了Redis BloomFilter實(shí)例。BloomFilter不需要存儲key,節(jié)省空間,在某些對保密要求非常嚴(yán)格的場合有優(yōu)勢。想要進(jìn)一步了解BloomFilter運(yùn)用實(shí)例的小伙伴可以了解一下這篇文章
    2021-09-09
  • Redisson 主從一致性問題詳解

    Redisson 主從一致性問題詳解

    這篇文章主要為大家介紹了Redisson 主從一致性問題詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪
    2022-08-08
  • 使用Redis實(shí)現(xiàn)延時任務(wù)的解決方案

    使用Redis實(shí)現(xiàn)延時任務(wù)的解決方案

    這篇文章主要介紹了使用Redis實(shí)現(xiàn)延時任務(wù)的解決方案,本文給大家介紹的非常詳細(xì),具有一定的參考借鑒價(jià)值,需要的朋友可以參考下
    2019-08-08
  • redis配置文件中常用配置詳解

    redis配置文件中常用配置詳解

    這篇文章主要介紹了redis配置文件中常用配置詳解,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2021-04-04
  • 基于Redis的3種分布式ID生成策略

    基于Redis的3種分布式ID生成策略

    在分布式系統(tǒng)設(shè)計(jì)中,全局唯一ID是一個基礎(chǔ)而關(guān)鍵的組件,隨著業(yè)務(wù)規(guī)模擴(kuò)大和系統(tǒng)架構(gòu)向微服務(wù)演進(jìn),傳統(tǒng)的單機(jī)自增ID已無法滿足需求,高并發(fā)、高可用的分布式ID生成方案成為構(gòu)建可靠分布式系統(tǒng)的必要條件,
    2025-08-08
  • redis全局命令set、get、keys使用方法

    redis全局命令set、get、keys使用方法

    這篇文章主要介紹了redis全局命令set、get、keys使用方法的相關(guān)資料,詳細(xì)講解了Redis的基本概念和常用命令,強(qiáng)調(diào)了在生產(chǎn)環(huán)境中避免使用keys命令的重要性,需要的朋友可以參考下
    2025-03-03
  • Redis如何設(shè)置過期時間

    Redis如何設(shè)置過期時間

    這篇文章主要介紹了Redis如何設(shè)置過期時間問題,具有很好的參考價(jià)值,希望對大家有所幫助,如有錯誤或未考慮完全的地方,望不吝賜教
    2025-04-04
  • 基于?Redis?實(shí)現(xiàn)接口限流的方式

    基于?Redis?實(shí)現(xiàn)接口限流的方式

    今天想和小伙伴們聊聊用?Redis?處理接口限流,這也是最近的?TienChin?項(xiàng)目涉及到這個知識點(diǎn)了,我就拎出來和大家聊聊這個話題
    2022-05-05
  • Redis事務(wù)處理的實(shí)現(xiàn)示例

    Redis事務(wù)處理的實(shí)現(xiàn)示例

    這篇文章主要介紹了Redis事務(wù)處理的實(shí)現(xiàn)示例,包括事務(wù)的原理、相關(guān)命令,如MULTI、EXEC、WATCH等、CAS樂觀鎖實(shí)現(xiàn)方式以及事務(wù)執(zhí)行步驟,感興趣的可以了解一下
    2025-10-10
  • Redis事務(wù),Redis實(shí)現(xiàn)悲觀鎖,樂觀鎖方式

    Redis事務(wù),Redis實(shí)現(xiàn)悲觀鎖,樂觀鎖方式

    文章介紹了Redis事務(wù)的概念、特點(diǎn)和執(zhí)行過程,區(qū)別于MySQL事務(wù)的ACID特性,詳細(xì)講解了未授權(quán)讀取、授權(quán)讀取、重復(fù)讀取和串行化四種隔離級別,并解析了悲觀鎖和樂觀鎖的定義與應(yīng)用場景,最后闡述了Redis通過版本號實(shí)現(xiàn)樂觀鎖的機(jī)制
    2026-05-05

最新評論

高州市| 阳曲县| 囊谦县| 左贡县| 临洮县| 娱乐| 长治县| 准格尔旗| 建水县| 平安县| 清河县| 徐汇区| 司法| 溧水县| 黄骅市| 阿拉善右旗| 衡山县| 资兴市| 万盛区| 北海市| 阳江市| 治县。| 内乡县| 丰城市| 太仓市| 渭南市| 北碚区| 邯郸市| 德庆县| 江华| 亚东县| 会理县| 高阳县| 洪湖市| 调兵山市| 犍为县| 乐陵市| 鄂托克前旗| 科尔| 开平市| 中阳县|