在Go语言项目开发过程中,权限管理是保障系统数据安全、规范用户操作的核心模块,很多中小型项目不需要复杂的权限体系,只需要实现基础的角色权限控制即可满足需求。基于RBAC(基于角色的访问控制)模型设计的简易权限管理方案,逻辑清晰且扩展性强,非常适合作为入门实践方案。

权限管理设计思路
简易权限管理通常采用用户-角色-权限的三层关联结构,核心逻辑是用户关联角色,角色关联权限,通过角色作为中间层解耦用户和权限的直接绑定,后续调整权限时只需要修改角色的权限配置,不需要逐个修改用户权限。
核心表结构设计
首先需要设计三张核心表,分别是用户表、角色表、权限表,以及两张关联表用户角色关联表、角色权限关联表,具体字段设计如下:
| 表名 | 核心字段 | 说明 |
|---|---|---|
| user | id, username, password | 存储用户基础信息 |
| role | id, role_name, role_desc | 存储角色信息 |
| permission | id, perm_name, perm_path | 存储权限信息,perm_path为接口路径 |
| user_role | id, user_id, role_id | 用户和角色的关联表 |
| role_permission | id, role_id, permission_id | 角色和权限的关联表 |
Golang核心实现逻辑
数据库模型定义
首先定义对应的Golang结构体,用于和数据库表映射:
package model
// User 用户模型
type User struct {
ID uint `gorm:"primaryKey"`
Username string `gorm:"size:50;not null"`
Password string `gorm:"size:100;not null"`
}
// Role 角色模型
type Role struct {
ID uint `gorm:"primaryKey"`
RoleName string `gorm:"size:50;not null"`
RoleDesc string `gorm:"size:200"`
}
// Permission 权限模型
type Permission struct {
ID uint `gorm:"primaryKey"`
PermName string `gorm:"size:50;not null"`
PermPath string `gorm:"size:200;not null"`
}
// UserRole 用户角色关联模型
type UserRole struct {
ID uint `gorm:"primaryKey"`
UserID uint `gorm:"not null"`
RoleID uint `gorm:"not null"`
}
// RolePermission 角色权限关联模型
type RolePermission struct {
ID uint `gorm:"primaryKey"`
RoleID uint `gorm:"not null"`
PermissionID uint `gorm:"not null"`
}
权限校验逻辑实现
权限校验的核心流程是:根据当前登录用户的ID,查询其关联的所有角色,再根据角色查询所有关联的权限,最后判断当前请求的接口路径是否在用户的权限列表中。
package service
import (
"errors"
"gorm.io/gorm"
"your_project/model"
)
type PermissionService struct {
DB *gorm.DB
}
// CheckPermission 校验用户是否有指定路径的访问权限
func (s *PermissionService) CheckPermission(userID uint, path string) (bool, error) {
// 1. 查询用户关联的角色ID列表
var userRoles []model.UserRole
if err := s.DB.Where("user_id = ?", userID).Find(&userRoles).Error; err != nil {
return false, err
}
if len(userRoles) == 0 {
return false, errors.New("用户未关联任何角色")
}
// 提取角色ID
roleIDs := make([]uint, 0, len(userRoles))
for _, ur := range userRoles {
roleIDs = append(roleIDs, ur.RoleID)
}
// 2. 根据角色ID查询关联的权限ID
var rolePerms []model.RolePermission
if err := s.DB.Where("role_id IN ?", roleIDs).Find(&rolePerms).Error; err != nil {
return false, err
}
if len(rolePerms) == 0 {
return false, nil
}
// 提取权限ID
permIDs := make([]uint, 0, len(rolePerms))
for _, rp := range rolePerms {
permIDs = append(permIDs, rp.PermissionID)
}
// 3. 查询权限列表,判断路径是否匹配
var perms []model.Permission
if err := s.DB.Where("id IN ?", permIDs).Find(&perms).Error; err != nil {
return false, err
}
for _, perm := range perms {
if perm.PermPath == path {
return true, nil
}
}
return false, nil
}
中间件集成示例
在Gin框架中可以封装成中间件,在接口请求前自动完成权限校验:
package middleware
import (
"net/http"
"your_project/service"
"github.com/gin-gonic/gin"
)
// AuthPermission 权限校验中间件
func AuthPermission(permService *service.PermissionService) gin.HandlerFunc {
return func(c *gin.Context) {
// 从上下文获取当前登录用户ID,实际项目中从token解析获取
userID, exists := c.Get("user_id")
if !exists {
c.JSON(http.StatusUnauthorized, gin.H{"msg": "未登录"})
c.Abort()
return
}
// 获取当前请求路径
reqPath := c.Request.URL.Path
// 校验权限
hasPerm, err := permService.CheckPermission(userID.(uint), reqPath)
if err != nil {
c.JSON(http.StatusInternalServerError, gin.H{"msg": "权限校验失败"})
c.Abort()
return
}
if !hasPerm {
c.JSON(http.StatusForbidden, gin.H{"msg": "无访问权限"})
c.Abort()
return
}
c.Next()
}
}
扩展优化建议
上述实现是基础版本,实际项目中可以根据需求做进一步优化:
- 增加权限缓存,避免每次请求都查询数据库,提升性能
- 支持权限通配符匹配,比如
/api/user/*可以匹配所有用户相关接口 - 增加权限分组,方便管理同模块的权限
- 添加操作日志,记录用户的权限操作行为
这种基于RBAC的简易权限管理方案,代码逻辑简单,扩展性强,足以满足大部分中小型Go语言项目的权限控制需求,开发者可以根据自身项目的实际场景调整表结构和校验逻辑。