需求整理
- 管理后台有超管权限,超管拥有所有权限
- 普通管理员可以设置角色,角色单选
- 角色可以赋予多个权限,权限多选
- 这样我们就实现了对普通管理员的角色和权限的灵活管理
文档说明
- 基于golang语言开发
- 基于gin网络框架开发
- 基于MySQL5.8开发
- 把权限管理部分封装成中间件,在rourter文件中引用
- 非核心代码已省略,用3个竖着排列的点号.表示
数据库表结构设计
管理员表

权限表

角色表

角色表permission字段示意

代码部分
路由文件
| package server |
| |
| import ( |
| . |
| . |
| . |
| "os" |
| "github.com/gin-gonic/gin" |
| ) |
| |
| |
| func NewRouter() *gin.Engine { |
| r := gin.Default() |
| |
| |
| . |
| . |
| . |
| |
| v1 := r.Group("/api/v1") |
| { |
| v1.POST("login", api.Login) |
| auth := v1.Group("") |
| |
| auth.Use(middleware.AuthRequired()) |
| |
| auth.Use(middleware.AuthCheckMiddleware) |
| { |
| . |
| . |
| . |
| |
| { |
| auth.GET("/school/", api.GetSchoolInfo) |
| } |
| . |
| . |
| . |
| } |
| |
| } |
| return r |
| } |
| |
权限校验中间件代码
| package middleware |
| |
| import ( |
| . |
| . |
| . |
| "fmt" |
| "github.com/gin-gonic/gin" |
| "net/http" |
| "strings" |
| ) |
| |
| var AuthCheckMiddleware = authCheck() |
| func authCheck() gin.HandlerFunc { |
| return func(c *gin.Context) { |
| if admin, _ := c.Get("admin"); admin != nil { |
| method := c.Request.Method |
| url := c.Request.URL.Path |
| adminInfo := admin.(**service.RunningClaims) |
| isSuper := (*adminInfo).IsSuper |
| roleId := (*adminInfo).RoleId |
| |
| if isSuper != 1 { |
| fmt.Println("method:", method) |
| fmt.Println("url:", url) |
| permissionFunc := strings.ToLower(fmt.Sprintf("%s_%s", method, url)) |
| haveAuth := model.CheckRolePermission(uint(roleId), permissionFunc) |
| fmt.Println("haveAuth ", haveAuth) |
| if !haveAuth { |
| c.JSON(http.StatusOK, api.ReturnJson{http.StatusForbidden, "", "无权访问"}) |
| c.Abort() |
| } |
| } |
| c.Next() |
| } |
| } |
| } |
| |
角色model层代码
- CheckRolePermission是关键代码
| |
| type StringArray []string |
| |
| |
| type Role struct { |
| Id int `gorm:"column:id" form:"id" json:"id" comment:"自增id" sql:"int(11),PRI"` |
| Name string `gorm:"column:name" form:"name" json:"name" comment:"角色名" sql:"varchar(255)"` |
| Description string `gorm:"column:description" form:"description" json:"description" comment:"描述" sql:"varchar(255)"` |
| Permission *StringArray `gorm:"type:json;column:permission" form:"permission" json:"permission" comment:"权限"` |
| } |
| |
| func (data *StringArray) Scan(val interface{}) (err error) { |
| if val == nil { |
| return nil |
| } |
| if payload, ok := val.([]byte); ok { |
| var value []string |
| err = json.Unmarshal(payload, &value) |
| if err == nil { |
| *data = value |
| } |
| } |
| return |
| } |
| |
| func CheckRolePermission(roleId uint, permissionFunc string) bool { |
| if roleId == 0 { |
| return false |
| } |
| |
| var myRole Role |
| err := DB.Where("id = ?", roleId).First(&myRole).Error |
| if err != gorm.ErrRecordNotFound { |
| fmt.Printf("%v", myRole) |
| permissions := myRole.Permission |
| permissions.Scan(permissions) |
| for _, permission := range *permissions { |
| fmt.Println("permissionFunc:", permissionFunc) |
| fmt.Println("permission:", permission) |
| if strings.HasPrefix(permissionFunc, permission) { |
| return true |
| } |
| } |
| } |
| return false |
| } |
运行效果
有权限
| { |
| "code": 403, |
| "data": "", |
| "message": "无权访问" |
| } |
无权限
| { |
| "code": 200, |
| "data": true, |
| "message": "更新成功" |
| } |
后续
下一章封装管理后台的操作日志管理:以中间件+goroutine的方式保存管理员的操作日志