1. What is RBAC?
RBAC (Role-Based Access Control) is a common permission management model. It controls access permissions through user (User), role (Role), Permission and their mapping relationships. The basic idea of RBAC is:
- The user is assigned one or more roles;
- Each role has certain permissions;
- The user's role is determined by whether he has permission to access a resource.
2. Why use Redis to implement RBAC?
In traditional RBAC designs, permission data is usually stored in a database (such as MySQL), but this method may have the following problems:
- Low query performance: multiple tables are required for each authentication, which affects the API response speed;
- Not suitable for high concurrency: the database connection pool is limited, which may become a bottleneck in high concurrency scenarios;
- Permission changes are inflexible: Database solutions usually require regular sync caches, otherwise the changes will not take effect immediately.
Advantages of using Redis as RBAC permission storage:
- High performance: Redis is an in-memory database and has extremely fast query speed;
- Low latency: Can be directly
O(1)
Query permission data without complex SQL statements; - Support dynamic permission changes: user permission changes can take effect in real time without waiting for database updates;
- Suitable for distributed systems: Multiple servers can share Redis permission data to avoid inconsistent states of different instances.
3. Design RBAC data structure
We use Redis as permission storage and design the following Key structure:
Key | Value | illustrate |
---|---|---|
user_roles:{user_id} | ["admin", "editor"] | User role list |
role_permissions:{role} | ["read", "write", "delete"] | Permission list for roles |
permission_routes:{permission} | ["GET:/users", "POST:/articles"] | Permission-corresponding API |
blacklist_tokens | Store logged out tokens | Invalidate JWT and support active logout |
4. Code implementation
We use Gin as the web framework and combine Redis for permission management.
📌 4.1 Installation dependencies
go get -u /gin-gonic/gin go get -u /golang-jwt/jwt/v5 go get -u /redis/go-redis/v9
📌 4.2 Initialize Redis
package main import ( "context" "fmt" "log" "/redis/go-redis/v9" ) // Initialize the Redis clientvar ctx = () var redisClient = (&{ Addr: "127.0.0.1:6379", // Connect to Redis}) // Initialize RBAC Role & Permission Mappingfunc setupRBAC() { // Role → Permissions (ctx, "role_permissions:admin", "read", "write", "delete") (ctx, "role_permissions:editor", "read", "write") (ctx, "role_permissions:viewer", "read") // Permissions → API (ctx, "permission_routes:read", "GET:/users", "GET:/articles") (ctx, "permission_routes:write", "POST:/articles", "PUT:/articles") (ctx, "permission_routes:delete", "DELETE:/articles") // User → Role (ctx, "user_roles:1", "admin") (ctx, "user_roles:2", "editor") (ctx, "user_roles:3", "viewer") ("RBAC permission mapping initialization is completed") }
📌 4.3 Generate JWT tokens
package main import ( "fmt" "time" "/golang-jwt/jwt/v5" ) // JWT keyvar jwtSecret = []byte("supersecretkey") // Generate JWT tokenfunc GenerateJWT(userID int) (string, error) { token := (jwt.SigningMethodHS256, { "user_id": userID, "exp": ().Add(24 * ).Unix(), // Valid for 24 hours }) return (jwtSecret) } // parse JWT tokenfunc ParseJWT(tokenString string) (int, error) { token, err := (tokenString, func(token *) (interface{}, error) { return jwtSecret, nil }) if err != nil || ! { return 0, ("invalid token") } claims, ok := .() if !ok { return 0, ("invalid claims") } return int(claims["user_id"].(float64)), nil }
📌 4.4 Authentication middleware
// Access permission checkfunc hasAccess(userID int, method, path string) bool { // 1. Obtain user role roles, err := (ctx, ("user_roles:%d", userID)).Result() if err != nil || len(roles) == 0 { return false } // 2. Traverse the role and obtain permissions for _, role := range roles { permissions, _ := (ctx, ("role_permissions:%s", role)).Result() for _, permission := range permissions { routes, _ := (ctx, ("permission_routes:%s", permission)).Result() for _, route := range routes { if route == ("%s:%s", method, path) { return true } } } } return false } // RBAC Middlewarefunc RBACMiddleware() { return func(c *) { tokenString := ("Authorization") if tokenString == "" { (401, {"error": "Token not provided"}) () return } // Analysis JWT userID, err := ParseJWT(tokenString) if err != nil { (401, {"error": "Token is invalid"}) () return } // Check permissions if !hasAccess(userID, , ()) { (403, {"error": "No access permission"}) () return } ("userID", userID) () } }
📌 4.5 API Interface
func main() { r := () setupRBAC() // Log in ("/login", func(c *) { userID := 1 // Suppose user 1 login token, _ := GenerateJWT(userID) (200, {"token": token}) }) // Protected API api := ("/api", RBACMiddleware()) ("/users", func(c *) { (200, {"message": "Get user list"}) }) ("/articles", func(c *) { (200, {"message": "Create an article"}) }) ("/articles", func(c *) { (200, {"message": "Delete Articles"}) }) (":8080") }
5. Plan summary
✅ Redis storage permissions (recommended): efficient and suitable for distributed
✅ RBAC permission mapping: role permission mapping is clear
✅JWT Authentication: Stateless, suitable for API Authentication
In this way, you can use Redis to design an efficient set of RBAC permission management and support API mapping!
This is the end of this article about Redis implementing RBAC permission management. For more related Redis RBAC permission content, please search for my previous articles or continue browsing the related articles below. I hope everyone will support me in the future!