3.9.4 RBAC 权限控制 #
基于角色的访问控制(Role-Based Access Control,RBAC)是一种广泛使用的权限管理模型。它通过角色来组织权限,用户通过分配角色来获得相应的权限,实现了权限管理的灵活性和可维护性。
RBAC 基础概念 #
RBAC 模型组成 #
RBAC 模型包含以下核心概念:
- 用户(User):系统的使用者
- 角色(Role):权限的集合,代表一种职能
- 权限(Permission):对资源的操作权限
- 资源(Resource):系统中的受保护对象
- 操作(Action):对资源可执行的动作
RBAC 关系模型 #
用户 ←→ 角色 ←→ 权限 ←→ 资源
↓ ↓ ↓ ↓
User Role Permission Resource
RBAC 层次结构 #
- RBAC0:基础模型,包含用户、角色、权限和会话
- RBAC1:角色层次模型,支持角色继承
- RBAC2:约束模型,支持职责分离等约束
- RBAC3:统一模型,结合 RBAC1 和 RBAC2
Go 中实现 RBAC #
数据模型设计 #
// models/rbac.go
package models
import (
"time"
"gorm.io/gorm"
)
// User 用户模型
type User struct {
ID uint `json:"id" gorm:"primaryKey"`
Username string `json:"username" gorm:"unique;not null"`
Email string `json:"email" gorm:"unique;not null"`
Password string `json:"-" gorm:"not null"`
IsActive bool `json:"is_active" gorm:"default:true"`
Roles []Role `json:"roles" gorm:"many2many:user_roles;"`
CreatedAt time.Time `json:"created_at"`
UpdatedAt time.Time `json:"updated_at"`
}
// Role 角色模型
type Role struct {
ID uint `json:"id" gorm:"primaryKey"`
Name string `json:"name" gorm:"unique;not null"`
DisplayName string `json:"display_name" gorm:"not null"`
Description string `json:"description"`
IsActive bool `json:"is_active" gorm:"default:true"`
Users []User `json:"users" gorm:"many2many:user_roles;"`
Permissions []Permission `json:"permissions" gorm:"many2many:role_permissions;"`
ParentID *uint `json:"parent_id" gorm:"index"`
Parent *Role `json:"parent" gorm:"foreignKey:ParentID"`
Children []Role `json:"children" gorm:"foreignKey:ParentID"`
CreatedAt time.Time `json:"created_at"`
UpdatedAt time.Time `json:"updated_at"`
}
// Permission 权限模型
type Permission struct {
ID uint `json:"id" gorm:"primaryKey"`
Name string `json:"name" gorm:"unique;not null"`
DisplayName string `json:"display_name" gorm:"not null"`
Description string `json:"description"`
Resource string `json:"resource" gorm:"not null"`
Action string `json:"action" gorm:"not null"`
IsActive bool `json:"is_active" gorm:"default:true"`
Roles []Role `json:"roles" gorm:"many2many:role_permissions;"`
CreatedAt time.Time `json:"created_at"`
UpdatedAt time.Time `json:"updated_at"`
}
// UserRole 用户角色关联表
type UserRole struct {
UserID uint `json:"user_id" gorm:"primaryKey"`
RoleID uint `json:"role_id" gorm:"primaryKey"`
AssignedBy uint `json:"assigned_by"`
AssignedAt time.Time `json:"assigned_at"`
ExpiresAt *time.Time `json:"expires_at"`
}
// RolePermission 角色权限关联表
type RolePermission struct {
RoleID uint `json:"role_id" gorm:"primaryKey"`
PermissionID uint `json:"permission_id" gorm:"primaryKey"`
GrantedBy uint `json:"granted_by"`
GrantedAt time.Time `json:"granted_at"`
}
// Resource 资源模型
type Resource struct {
ID uint `json:"id" gorm:"primaryKey"`
Name string `json:"name" gorm:"unique;not null"`
DisplayName string `json:"display_name" gorm:"not null"`
Description string `json:"description"`
Type string `json:"type" gorm:"not null"` // api, menu, button, data
Path string `json:"path"`
Method string `json:"method"`
ParentID *uint `json:"parent_id" gorm:"index"`
Parent *Resource `json:"parent" gorm:"foreignKey:ParentID"`
Children []Resource `json:"children" gorm:"foreignKey:ParentID"`
IsActive bool `json:"is_active" gorm:"default:true"`
CreatedAt time.Time `json:"created_at"`
UpdatedAt time.Time `json:"updated_at"`
}
RBAC 服务层 #
// services/rbac.go
package services
import (
"errors"
"fmt"
"strings"
"time"
"gorm.io/gorm"
"your-project/models"
)
var (
ErrUserNotFound = errors.New("用户不存在")
ErrRoleNotFound = errors.New("角色不存在")
ErrPermissionNotFound = errors.New("权限不存在")
ErrPermissionDenied = errors.New("权限不足")
ErrRoleExists = errors.New("角色已存在")
ErrPermissionExists = errors.New("权限已存在")
)
// RBACService RBAC服务
type RBACService struct {
db *gorm.DB
}
// NewRBACService 创建RBAC服务
func NewRBACService(db *gorm.DB) *RBACService {
return &RBACService{db: db}
}
// CreateRole 创建角色
func (s *RBACService) CreateRole(role *models.Role) error {
var existingRole models.Role
if err := s.db.Where("name = ?", role.Name).First(&existingRole).Error; err == nil {
return ErrRoleExists
}
return s.db.Create(role).Error
}
// GetRole 获取角色
func (s *RBACService) GetRole(roleID uint) (*models.Role, error) {
var role models.Role
if err := s.db.Preload("Permissions").Preload("Users").First(&role, roleID).Error; err != nil {
if err == gorm.ErrRecordNotFound {
return nil, ErrRoleNotFound
}
return nil, err
}
return &role, nil
}
// GetRoleByName 根据名称获取角色
func (s *RBACService) GetRoleByName(name string) (*models.Role, error) {
var role models.Role
if err := s.db.Preload("Permissions").Where("name = ?", name).First(&role).Error; err != nil {
if err == gorm.ErrRecordNotFound {
return nil, ErrRoleNotFound
}
return nil, err
}
return &role, nil
}
// CreatePermission 创建权限
func (s *RBACService) CreatePermission(permission *models.Permission) error {
var existingPermission models.Permission
if err := s.db.Where("name = ?", permission.Name).First(&existingPermission).Error; err == nil {
return ErrPermissionExists
}
return s.db.Create(permission).Error
}
// GetPermission 获取权限
func (s *RBACService) GetPermission(permissionID uint) (*models.Permission, error) {
var permission models.Permission
if err := s.db.First(&permission, permissionID).Error; err != nil {
if err == gorm.ErrRecordNotFound {
return nil, ErrPermissionNotFound
}
return nil, err
}
return &permission, nil
}
// AssignRoleToUser 为用户分配角色
func (s *RBACService) AssignRoleToUser(userID, roleID, assignedBy uint) error {
// 检查用户是否存在
var user models.User
if err := s.db.First(&user, userID).Error; err != nil {
return ErrUserNotFound
}
// 检查角色是否存在
var role models.Role
if err := s.db.First(&role, roleID).Error; err != nil {
return ErrRoleNotFound
}
// 检查是否已经分配
var userRole models.UserRole
if err := s.db.Where("user_id = ? AND role_id = ?", userID, roleID).First(&userRole).Error; err == nil {
return errors.New("用户已拥有该角色")
}
// 创建用户角色关联
userRole = models.UserRole{
UserID: userID,
RoleID: roleID,
AssignedBy: assignedBy,
AssignedAt: time.Now(),
}
return s.db.Create(&userRole).Error
}
// RevokeRoleFromUser 撤销用户角色
func (s *RBACService) RevokeRoleFromUser(userID, roleID uint) error {
return s.db.Where("user_id = ? AND role_id = ?", userID, roleID).Delete(&models.UserRole{}).Error
}
// AssignPermissionToRole 为角色分配权限
func (s *RBACService) AssignPermissionToRole(roleID, permissionID, grantedBy uint) error {
// 检查角色是否存在
var role models.Role
if err := s.db.First(&role, roleID).Error; err != nil {
return ErrRoleNotFound
}
// 检查权限是否存在
var permission models.Permission
if err := s.db.First(&permission, permissionID).Error; err != nil {
return ErrPermissionNotFound
}
// 检查是否已经分配
var rolePermission models.RolePermission
if err := s.db.Where("role_id = ? AND permission_id = ?", roleID, permissionID).First(&rolePermission).Error; err == nil {
return errors.New("角色已拥有该权限")
}
// 创建角色权限关联
rolePermission = models.RolePermission{
RoleID: roleID,
PermissionID: permissionID,
GrantedBy: grantedBy,
GrantedAt: time.Now(),
}
return s.db.Create(&rolePermission).Error
}
// RevokePermissionFromRole 撤销角色权限
func (s *RBACService) RevokePermissionFromRole(roleID, permissionID uint) error {
return s.db.Where("role_id = ? AND permission_id = ?", roleID, permissionID).Delete(&models.RolePermission{}).Error
}
// GetUserRoles 获取用户角色
func (s *RBACService) GetUserRoles(userID uint) ([]models.Role, error) {
var user models.User
if err := s.db.Preload("Roles.Permissions").First(&user, userID).Error; err != nil {
return nil, ErrUserNotFound
}
return user.Roles, nil
}
// GetUserPermissions 获取用户权限(包括角色继承)
func (s *RBACService) GetUserPermissions(userID uint) ([]models.Permission, error) {
roles, err := s.GetUserRoles(userID)
if err != nil {
return nil, err
}
permissionMap := make(map[uint]models.Permission)
for _, role := range roles {
// 获取角色直接权限
for _, permission := range role.Permissions {
permissionMap[permission.ID] = permission
}
// 获取角色继承权限
inheritedPermissions, err := s.getRoleInheritedPermissions(role.ID)
if err != nil {
continue
}
for _, permission := range inheritedPermissions {
permissionMap[permission.ID] = permission
}
}
permissions := make([]models.Permission, 0, len(permissionMap))
for _, permission := range permissionMap {
permissions = append(permissions, permission)
}
return permissions, nil
}
// getRoleInheritedPermissions 获取角色继承的权限
func (s *RBACService) getRoleInheritedPermissions(roleID uint) ([]models.Permission, error) {
var role models.Role
if err := s.db.Preload("Parent.Permissions").First(&role, roleID).Error; err != nil {
return nil, err
}
var permissions []models.Permission
// 递归获取父角色权限
if role.Parent != nil {
permissions = append(permissions, role.Parent.Permissions...)
parentPermissions, err := s.getRoleInheritedPermissions(role.Parent.ID)
if err == nil {
permissions = append(permissions, parentPermissions...)
}
}
return permissions, nil
}
// CheckPermission 检查用户权限
func (s *RBACService) CheckPermission(userID uint, resource, action string) (bool, error) {
permissions, err := s.GetUserPermissions(userID)
if err != nil {
return false, err
}
for _, permission := range permissions {
if permission.Resource == resource && permission.Action == action {
return true, nil
}
// 支持通配符权限
if permission.Resource == "*" || permission.Action == "*" {
return true, nil
}
// 支持资源层次权限
if strings.HasPrefix(resource, permission.Resource+".") {
return true, nil
}
}
return false, nil
}
// CheckRole 检查用户角色
func (s *RBACService) CheckRole(userID uint, roleName string) (bool, error) {
roles, err := s.GetUserRoles(userID)
if err != nil {
return false, err
}
for _, role := range roles {
if role.Name == roleName {
return true, nil
}
}
return false, nil
}
// GetRoleHierarchy 获取角色层次结构
func (s *RBACService) GetRoleHierarchy() ([]models.Role, error) {
var roles []models.Role
if err := s.db.Preload("Children").Where("parent_id IS NULL").Find(&roles).Error; err != nil {
return nil, err
}
return roles, nil
}
RBAC 中间件 #
// middleware/rbac.go
package middleware
import (
"net/http"
"strings"
"github.com/gin-gonic/gin"
"your-project/services"
)
// RBACMiddleware RBAC权限中间件
func RBACMiddleware(rbacService *services.RBACService) gin.HandlerFunc {
return func(c *gin.Context) {
// 获取用户ID(假设已通过认证中间件设置)
userID, exists := c.Get("user_id")
if !exists {
c.JSON(http.StatusUnauthorized, gin.H{
"error": "未认证用户",
})
c.Abort()
return
}
// 将RBAC服务添加到上下文
c.Set("rbac_service", rbacService)
c.Set("current_user_id", userID)
c.Next()
}
}
// RequirePermission 要求特定权限的中间件
func RequirePermission(resource, action string) gin.HandlerFunc {
return func(c *gin.Context) {
rbacService, exists := c.Get("rbac_service")
if !exists {
c.JSON(http.StatusInternalServerError, gin.H{
"error": "RBAC服务未初始化",
})
c.Abort()
return
}
userID, exists := c.Get("current_user_id")
if !exists {
c.JSON(http.StatusUnauthorized, gin.H{
"error": "用户未认证",
})
c.Abort()
return
}
service := rbacService.(*services.RBACService)
hasPermission, err := service.CheckPermission(userID.(uint), resource, action)
if err != nil {
c.JSON(http.StatusInternalServerError, gin.H{
"error": "权限检查失败",
})
c.Abort()
return
}
if !hasPermission {
c.JSON(http.StatusForbidden, gin.H{
"error": "权限不足",
"required_permission": map[string]string{
"resource": resource,
"action": action,
},
})
c.Abort()
return
}
c.Next()
}
}
// RequireRole 要求特定角色的中间件
func RequireRole(roleName string) gin.HandlerFunc {
return func(c *gin.Context) {
rbacService, exists := c.Get("rbac_service")
if !exists {
c.JSON(http.StatusInternalServerError, gin.H{
"error": "RBAC服务未初始化",
})
c.Abort()
return
}
userID, exists := c.Get("current_user_id")
if !exists {
c.JSON(http.StatusUnauthorized, gin.H{
"error": "用户未认证",
})
c.Abort()
return
}
service := rbacService.(*services.RBACService)
hasRole, err := service.CheckRole(userID.(uint), roleName)
if err != nil {
c.JSON(http.StatusInternalServerError, gin.H{
"error": "角色检查失败",
})
c.Abort()
return
}
if !hasRole {
c.JSON(http.StatusForbidden, gin.H{
"error": "角色权限不足",
"required_role": roleName,
})
c.Abort()
return
}
c.Next()
}
}
// RequireAnyRole 要求任意角色的中间件
func RequireAnyRole(roleNames ...string) gin.HandlerFunc {
return func(c *gin.Context) {
rbacService, exists := c.Get("rbac_service")
if !exists {
c.JSON(http.StatusInternalServerError, gin.H{
"error": "RBAC服务未初始化",
})
c.Abort()
return
}
userID, exists := c.Get("current_user_id")
if !exists {
c.JSON(http.StatusUnauthorized, gin.H{
"error": "用户未认证",
})
c.Abort()
return
}
service := rbacService.(*services.RBACService)
for _, roleName := range roleNames {
hasRole, err := service.CheckRole(userID.(uint), roleName)
if err == nil && hasRole {
c.Next()
return
}
}
c.JSON(http.StatusForbidden, gin.H{
"error": "角色权限不足",
"required_roles": roleNames,
})
c.Abort()
}
}
// DynamicPermissionMiddleware 动态权限中间件
func DynamicPermissionMiddleware() gin.HandlerFunc {
return func(c *gin.Context) {
rbacService, exists := c.Get("rbac_service")
if !exists {
c.JSON(http.StatusInternalServerError, gin.H{
"error": "RBAC服务未初始化",
})
c.Abort()
return
}
userID, exists := c.Get("current_user_id")
if !exists {
c.JSON(http.StatusUnauthorized, gin.H{
"error": "用户未认证",
})
c.Abort()
return
}
// 根据请求路径和方法动态确定所需权限
resource := getResourceFromPath(c.FullPath())
action := getActionFromMethod(c.Request.Method)
service := rbacService.(*services.RBACService)
hasPermission, err := service.CheckPermission(userID.(uint), resource, action)
if err != nil {
c.JSON(http.StatusInternalServerError, gin.H{
"error": "权限检查失败",
})
c.Abort()
return
}
if !hasPermission {
c.JSON(http.StatusForbidden, gin.H{
"error": "权限不足",
"required_permission": map[string]string{
"resource": resource,
"action": action,
},
})
c.Abort()
return
}
c.Next()
}
}
// getResourceFromPath 从路径获取资源名
func getResourceFromPath(path string) string {
parts := strings.Split(strings.Trim(path, "/"), "/")
if len(parts) >= 3 {
return parts[2] // /api/v1/users -> users
}
return "unknown"
}
// getActionFromMethod 从HTTP方法获取操作名
func getActionFromMethod(method string) string {
switch method {
case "GET":
return "read"
case "POST":
return "create"
case "PUT", "PATCH":
return "update"
case "DELETE":
return "delete"
default:
return "unknown"
}
}
RBAC 控制器 #
// controllers/rbac.go
package controllers
import (
"net/http"
"strconv"
"github.com/gin-gonic/gin"
"your-project/models"
"your-project/services"
)
type RBACController struct {
rbacService *services.RBACService
}
func NewRBACController(rbacService *services.RBACService) *RBACController {
return &RBACController{
rbacService: rbacService,
}
}
// CreateRole 创建角色
func (ctrl *RBACController) CreateRole(c *gin.Context) {
var req struct {
Name string `json:"name" binding:"required"`
DisplayName string `json:"display_name" binding:"required"`
Description string `json:"description"`
ParentID *uint `json:"parent_id"`
}
if err := c.ShouldBindJSON(&req); err != nil {
c.JSON(http.StatusBadRequest, gin.H{
"error": err.Error(),
})
return
}
role := &models.Role{
Name: req.Name,
DisplayName: req.DisplayName,
Description: req.Description,
ParentID: req.ParentID,
}
if err := ctrl.rbacService.CreateRole(role); err != nil {
c.JSON(http.StatusConflict, gin.H{
"error": err.Error(),
})
return
}
c.JSON(http.StatusCreated, gin.H{
"message": "角色创建成功",
"role": role,
})
}
// GetRoles 获取角色列表
func (ctrl *RBACController) GetRoles(c *gin.Context) {
roles, err := ctrl.rbacService.GetRoleHierarchy()
if err != nil {
c.JSON(http.StatusInternalServerError, gin.H{
"error": "获取角色列表失败",
})
return
}
c.JSON(http.StatusOK, gin.H{
"roles": roles,
})
}
// CreatePermission 创建权限
func (ctrl *RBACController) CreatePermission(c *gin.Context) {
var req struct {
Name string `json:"name" binding:"required"`
DisplayName string `json:"display_name" binding:"required"`
Description string `json:"description"`
Resource string `json:"resource" binding:"required"`
Action string `json:"action" binding:"required"`
}
if err := c.ShouldBindJSON(&req); err != nil {
c.JSON(http.StatusBadRequest, gin.H{
"error": err.Error(),
})
return
}
permission := &models.Permission{
Name: req.Name,
DisplayName: req.DisplayName,
Description: req.Description,
Resource: req.Resource,
Action: req.Action,
}
if err := ctrl.rbacService.CreatePermission(permission); err != nil {
c.JSON(http.StatusConflict, gin.H{
"error": err.Error(),
})
return
}
c.JSON(http.StatusCreated, gin.H{
"message": "权限创建成功",
"permission": permission,
})
}
// AssignRoleToUser 为用户分配角色
func (ctrl *RBACController) AssignRoleToUser(c *gin.Context) {
userIDStr := c.Param("user_id")
userID, err := strconv.ParseUint(userIDStr, 10, 32)
if err != nil {
c.JSON(http.StatusBadRequest, gin.H{
"error": "无效的用户ID",
})
return
}
var req struct {
RoleID uint `json:"role_id" binding:"required"`
}
if err := c.ShouldBindJSON(&req); err != nil {
c.JSON(http.StatusBadRequest, gin.H{
"error": err.Error(),
})
return
}
currentUserID, _ := c.Get("current_user_id")
if err := ctrl.rbacService.AssignRoleToUser(uint(userID), req.RoleID, currentUserID.(uint)); err != nil {
c.JSON(http.StatusBadRequest, gin.H{
"error": err.Error(),
})
return
}
c.JSON(http.StatusOK, gin.H{
"message": "角色分配成功",
})
}
// RevokeRoleFromUser 撤销用户角色
func (ctrl *RBACController) RevokeRoleFromUser(c *gin.Context) {
userIDStr := c.Param("user_id")
userID, err := strconv.ParseUint(userIDStr, 10, 32)
if err != nil {
c.JSON(http.StatusBadRequest, gin.H{
"error": "无效的用户ID",
})
return
}
roleIDStr := c.Param("role_id")
roleID, err := strconv.ParseUint(roleIDStr, 10, 32)
if err != nil {
c.JSON(http.StatusBadRequest, gin.H{
"error": "无效的角色ID",
})
return
}
if err := ctrl.rbacService.RevokeRoleFromUser(uint(userID), uint(roleID)); err != nil {
c.JSON(http.StatusBadRequest, gin.H{
"error": err.Error(),
})
return
}
c.JSON(http.StatusOK, gin.H{
"message": "角色撤销成功",
})
}
// AssignPermissionToRole 为角色分配权限
func (ctrl *RBACController) AssignPermissionToRole(c *gin.Context) {
roleIDStr := c.Param("role_id")
roleID, err := strconv.ParseUint(roleIDStr, 10, 32)
if err != nil {
c.JSON(http.StatusBadRequest, gin.H{
"error": "无效的角色ID",
})
return
}
var req struct {
PermissionID uint `json:"permission_id" binding:"required"`
}
if err := c.ShouldBindJSON(&req); err != nil {
c.JSON(http.StatusBadRequest, gin.H{
"error": err.Error(),
})
return
}
currentUserID, _ := c.Get("current_user_id")
if err := ctrl.rbacService.AssignPermissionToRole(uint(roleID), req.PermissionID, currentUserID.(uint)); err != nil {
c.JSON(http.StatusBadRequest, gin.H{
"error": err.Error(),
})
return
}
c.JSON(http.StatusOK, gin.H{
"message": "权限分配成功",
})
}
// GetUserPermissions 获取用户权限
func (ctrl *RBACController) GetUserPermissions(c *gin.Context) {
userIDStr := c.Param("user_id")
userID, err := strconv.ParseUint(userIDStr, 10, 32)
if err != nil {
c.JSON(http.StatusBadRequest, gin.H{
"error": "无效的用户ID",
})
return
}
permissions, err := ctrl.rbacService.GetUserPermissions(uint(userID))
if err != nil {
c.JSON(http.StatusInternalServerError, gin.H{
"error": err.Error(),
})
return
}
c.JSON(http.StatusOK, gin.H{
"permissions": permissions,
})
}
// CheckPermission 检查用户权限
func (ctrl *RBACController) CheckPermission(c *gin.Context) {
userIDStr := c.Param("user_id")
userID, err := strconv.ParseUint(userIDStr, 10, 32)
if err != nil {
c.JSON(http.StatusBadRequest, gin.H{
"error": "无效的用户ID",
})
return
}
resource := c.Query("resource")
action := c.Query("action")
if resource == "" || action == "" {
c.JSON(http.StatusBadRequest, gin.H{
"error": "缺少resource或action参数",
})
return
}
hasPermission, err := ctrl.rbacService.CheckPermission(uint(userID), resource, action)
if err != nil {
c.JSON(http.StatusInternalServerError, gin.H{
"error": err.Error(),
})
return
}
c.JSON(http.StatusOK, gin.H{
"has_permission": hasPermission,
"resource": resource,
"action": action,
})
}
权限初始化 #
// pkg/rbac/init.go
package rbac
import (
"log"
"your-project/models"
"your-project/services"
)
// InitializeRBAC 初始化RBAC系统
func InitializeRBAC(rbacService *services.RBACService) error {
// 创建基础角色
roles := []models.Role{
{
Name: "super_admin",
DisplayName: "超级管理员",
Description: "系统超级管理员,拥有所有权限",
},
{
Name: "admin",
DisplayName: "管理员",
Description: "系统管理员",
},
{
Name: "user",
DisplayName: "普通用户",
Description: "普通用户",
},
{
Name: "guest",
DisplayName: "访客",
Description: "访客用户",
},
}
for _, role := range roles {
if err := rbacService.CreateRole(&role); err != nil {
log.Printf("创建角色失败: %v", err)
}
}
// 创建基础权限
permissions := []models.Permission{
// 用户管理权限
{Name: "user.create", DisplayName: "创建用户", Resource: "user", Action: "create"},
{Name: "user.read", DisplayName: "查看用户", Resource: "user", Action: "read"},
{Name: "user.update", DisplayName: "更新用户", Resource: "user", Action: "update"},
{Name: "user.delete", DisplayName: "删除用户", Resource: "user", Action: "delete"},
// 角色管理权限
{Name: "role.create", DisplayName: "创建角色", Resource: "role", Action: "create"},
{Name: "role.read", DisplayName: "查看角色", Resource: "role", Action: "read"},
{Name: "role.update", DisplayName: "更新角色", Resource: "role", Action: "update"},
{Name: "role.delete", DisplayName: "删除角色", Resource: "role", Action: "delete"},
// 权限管理权限
{Name: "permission.create", DisplayName: "创建权限", Resource: "permission", Action: "create"},
{Name: "permission.read", DisplayName: "查看权限", Resource: "permission", Action: "read"},
{Name: "permission.update", DisplayName: "更新权限", Resource: "permission", Action: "update"},
{Name: "permission.delete", DisplayName: "删除权限", Resource: "permission", Action: "delete"},
// 系统权限
{Name: "system.admin", DisplayName: "系统管理", Resource: "system", Action: "admin"},
{Name: "system.monitor", DisplayName: "系统监控", Resource: "system", Action: "monitor"},
// 通配符权限
{Name: "all.all", DisplayName: "所有权限", Resource: "*", Action: "*"},
}
for _, permission := range permissions {
if err := rbacService.CreatePermission(&permission); err != nil {
log.Printf("创建权限失败: %v", err)
}
}
// 为角色分配权限
rolePermissions := map[string][]string{
"super_admin": {"all.all"},
"admin": {
"user.create", "user.read", "user.update", "user.delete",
"role.read", "permission.read",
"system.monitor",
},
"user": {
"user.read",
},
"guest": {},
}
for roleName, permissionNames := range rolePermissions {
role, err := rbacService.GetRoleByName(roleName)
if err != nil {
continue
}
for _, permissionName := range permissionNames {
// 这里需要根据权限名称获取权限ID,然后分配
// 简化处理,实际应用中需要完善
log.Printf("为角色 %s 分配权限 %s", roleName, permissionName)
}
}
return nil
}
完整示例 #
// main.go
package main
import (
"log"
"github.com/gin-gonic/gin"
"gorm.io/driver/sqlite"
"gorm.io/gorm"
"your-project/controllers"
"your-project/middleware"
"your-project/models"
"your-project/pkg/rbac"
"your-project/services"
)
func main() {
// 初始化数据库
db, err := gorm.Open(sqlite.Open("rbac.db"), &gorm.Config{})
if err != nil {
log.Fatal("数据库连接失败:", err)
}
// 自动迁移
db.AutoMigrate(
&models.User{},
&models.Role{},
&models.Permission{},
&models.Resource{},
&models.UserRole{},
&models.RolePermission{},
)
// 初始化服务
rbacService := services.NewRBACService(db)
// 初始化RBAC系统
if err := rbac.InitializeRBAC(rbacService); err != nil {
log.Printf("RBAC初始化失败: %v", err)
}
// 初始化控制器
rbacController := controllers.NewRBACController(rbacService)
// 初始化路由
r := gin.Default()
// 使用RBAC中间件
r.Use(middleware.RBACMiddleware(rbacService))
// API路由
api := r.Group("/api/v1")
{
// 角色管理
roles := api.Group("/roles")
roles.Use(middleware.RequirePermission("role", "read"))
{
roles.GET("", rbacController.GetRoles)
roles.POST("", middleware.RequirePermission("role", "create"), rbacController.CreateRole)
}
// 权限管理
permissions := api.Group("/permissions")
permissions.Use(middleware.RequirePermission("permission", "read"))
{
permissions.POST("", middleware.RequirePermission("permission", "create"), rbacController.CreatePermission)
}
// 用户角色管理
users := api.Group("/users")
users.Use(middleware.RequirePermission("user", "read"))
{
users.POST("/:user_id/roles", middleware.RequirePermission("user", "update"), rbacController.AssignRoleToUser)
users.DELETE("/:user_id/roles/:role_id", middleware.RequirePermission("user", "update"), rbacController.RevokeRoleFromUser)
users.GET("/:user_id/permissions", rbacController.GetUserPermissions)
users.GET("/:user_id/check-permission", rbacController.CheckPermission)
}
// 角色权限管理
rolePermissions := api.Group("/roles/:role_id/permissions")
rolePermissions.Use(middleware.RequirePermission("role", "update"))
{
rolePermissions.POST("", rbacController.AssignPermissionToRole)
}
// 管理员专用接口
admin := api.Group("/admin")
admin.Use(middleware.RequireRole("admin"))
{
admin.GET("/dashboard", func(c *gin.Context) {
c.JSON(200, gin.H{"message": "管理员仪表板"})
})
}
// 超级管理员专用接口
superAdmin := api.Group("/super-admin")
superAdmin.Use(middleware.RequireRole("super_admin"))
{
superAdmin.GET("/system", func(c *gin.Context) {
c.JSON(200, gin.H{"message": "系统管理"})
})
}
// 动态权限控制的接口
dynamic := api.Group("/dynamic")
dynamic.Use(middleware.DynamicPermissionMiddleware())
{
dynamic.GET("/data", func(c *gin.Context) {
c.JSON(200, gin.H{"message": "数据"})
})
dynamic.POST("/data", func(c *gin.Context) {
c.JSON(200, gin.H{"message": "数据已创建"})
})
}
}
log.Println("RBAC服务器启动在 :8080")
r.Run(":8080")
}
RBAC 最佳实践 #
1. 权限设计原则 #
- 最小权限原则:用户只获得完成工作所需的最小权限
- 职责分离:敏感操作需要多个角色协作完成
- 权限继承:合理设计角色层次结构
- 动态权限:支持运行时权限检查和调整
2. 性能优化 #
- 权限缓存:缓存用户权限信息
- 批量检查:一次性检查多个权限
- 索引优化:为关联表创建合适的索引
- 懒加载:按需加载权限信息
3. 安全考虑 #
- 权限审计:记录权限变更日志
- 定期清理:清理过期的权限分配
- 权限验证:在关键操作前再次验证权限
- 防止提权:防止用户获得超出预期的权限
RBAC 提供了一种灵活而强大的权限管理机制,通过合理的设计和实现,可以满足复杂企业应用的权限控制需求。