需求整理
- 管理后台有超管权限,超管拥有所有权限
- 普通管理员可以设置角色,角色单选
- 角色可以赋予多个权限,权限多选
- 这样我们就实现了对普通管理员的角色和权限的灵活管理
文档说明
- 基于golang语言开发
- 基于gin网络框架开发
- 基于MySQL5.8开发
- 把权限管理部分封装成中间件,在rourter文件中引用
- 非核心代码已省略,用3个竖着排列的点号.表示
数据库表结构设计
管理员表
权限表
角色表
角色表permission字段示意
代码部分
路由文件
package server import ( . . . "os" "github.com/gin-gonic/gin" ) // NewRouter 路由配置 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": "更新成功" }
公众号:程序员升级打怪之旅
微信号:wangzhongyang1993