一步步实现微服务权限管理系统(9)
前言
- 前端参考了很多框架,可谓百花齐放,但很多封装过剩,不利于学习和应用,最终我选择了 [vue-pure-admin](https://github.com/pure-admin/vue-pure-admin)
- 后端我将使用 go-zero 来带领大家一步步实现一个权限管理系统
- 本系列项目存放在 purezeroadmin 中,每一部分我都将打tag,并保证每个tag能正常运行。请多点赞和评论。
- 后面示例均为
purezeroadmin
项目为例,你们可以根据需要自建工程来进行试验。均采用vscode
进行试验。 go-zero
常用命令我将放入其对应的makefile
文件中。
本节概述
- casbin 是一个非常流行的访问控制模型,用来RBAC权限控制非常方便, 参考 https://casbin.org/zh/docs/rbac
- 先将路由所对应的权限映射为casbin的文件测试
- 之前生成路由树的逻辑中权限判断可以交给
casbin
来做了
后端修改
测试 casbin
- 创建
casbin.conf
[request_definition]
r = sub, obj, act
[policy_definition]
p = sub, obj, act
[role_definition]
g = _, _
[policy_effect]
e = some(where (p.eft == allow))
[matchers]
m = g(r.sub, p.sub) && r.obj == p.obj && r.act == p.act || r.sub == "admin"
- 创建
casbin.csv
p, 1, permission:btn:add, get
p, 2, permission:btn:edit, get
p, 3, permission:btn:delete, get
p, 1000000, /permission, get
p, 1010000, /permission/page/index, get
p, 1020000, /permission/button, get
p, 1020100, /permission/button/router, get
p, 1020200, /permission/button/login, get
g, 1, 1020100
g, 2, 1020100
g, 3, 1020100
g, common, 1000000
g, common, 1020000
g, common, 1
g, common, 2
g, common, 1020200
- 测试请求
common, /permission, get
common, /permission/page/index, get
common, /permission/button, get
common, /permission/button/router, get
common, /permission/button/login, get
common, permission:btn:add, get
common, permission:btn:edit, get
common, permission:btn:delete, get
admin, /permission, get
admin, /permission/page/index, get
admin, /permission/button, get
admin, /permission/button/router, get
admin, /permission/button/login, get
admin, permission:btn:add, get
admin, permission:btn:edit, get
admin, permission:btn:delete, get
- 执行结果
true Reason: ["1000000","/permission","get"]
false
true Reason: ["1020000","/permission/button","get"]
true Reason: ["1020100","/permission/button/router","get"]
true Reason: ["1020200","/permission/button/login","get"]
true Reason: ["1","permission:btn:add","get"]
true Reason: ["2","permission:btn:edit","get"]
false
// ignore
true Reason: ["1","permission:btn:add","get"]
true Reason: ["1","permission:btn:add","get"]
true Reason: ["1","permission:btn:add","get"]
true Reason: ["1","permission:btn:add","get"]
true Reason: ["1","permission:btn:add","get"]
true Reason: ["1","permission:btn:add","get"]
true Reason: ["1","permission:btn:add","get"]
true Reason: ["1","permission:btn:add","get"]
// ignore
可根据上述文件在 https://casbin.org/zh/editor 进行测试
permission:btn:add 这些是为了查看调用所以映射了subject
casbin
引入到后端
- 配置信息修改
user-api/etc/user-api.yaml
# casbin
Casbin:
ModelFile: "casbin.conf"
PolicyFile: "casbin.csv"
user-api/internal/config/config.go
type Config struct {
...
Casbin struct {
ModelFile string
PolicyFile string
}
}
- 修改服务上下文
user-api/internal/svc/servicecontext.go
type ServiceContext struct {
Config config.Config
TbUserModel models.TbUserModel
TbRoleModel models.TbRoleModel
TbRouterModel models.TbRouterModel
Enforcer *casbin.SyncedEnforcer
}
func NewServiceContext(c config.Config) *ServiceContext {
conn := sqlx.NewMysql(c.Dsn)
enforcer, err := casbin.NewSyncedEnforcer(c.Casbin.ModelFile, c.Casbin.PolicyFile)
if err != nil {
logx.Errorf("Error on NewSyncedEnforcer: %+v", err)
return nil
}
return &ServiceContext{
Config: c,
TbUserModel: models.NewTbUserModel(conn),
TbRoleModel: models.NewTbRoleModel(conn),
TbRouterModel: models.NewTbRouterModel(conn),
Enforcer: enforcer,
}
}
user-api/helper/helper.go
判断逻辑改成casbin来判断
func RouterToData(svcCtx *svc.ServiceContext, router *models.TbRouter, isAdmin bool, roles, permissions []string) (routerData *types.RouterData, err error) {
routerData = &types.RouterData{
Path: router.Path,
Name: router.Name,
Component: router.Component,
Meta: types.Meta{
Title: router.MetaTitle,
Icon: router.MetaIcon,
Rank: router.MetaRank,
},
}
pass := false
for _, role := range roles {
getPass, _ := svcCtx.Enforcer.Enforce(role, routerData.Path, "get")
if getPass {
pass = true
}
}
for _, permission := range permissions {
getPass, _ := svcCtx.Enforcer.Enforce(permission, routerData.Path, "get")
if getPass {
pass = true
}
}
if !pass {
return nil, nil
}
if router.MetaRoles.Valid {
routerData.Meta.Roles, err = jsonutil.ToArray[string](router.MetaRoles.String)
if err != nil {
return nil, err
}
}
if router.MetaAuths.Valid {
routerData.Meta.Auths, err = jsonutil.ToArray[string](router.MetaAuths.String)
if err != nil {
return nil, err
}
}
return routerData, nil
}
测试
- 前后端测试,通过
tag版本
purezeroadmin
项目下
git checkout v1.8.0
接下来
casbin 规则持久化