当前位置: 首页 > news >正文

go-Casbin使用

本次测试代码是基于单租户的RBAC鉴权

依赖

github.com/casbin/casbin/v2
github.com/casbin/gorm-adapter/v2

文件存储规则文件

model.pml

[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

policy.csv

p, admin, /user, write
p, admin, /user, read
p, admin, /order, write
p, admin, /order, read
p, admin, /user, put
p, systemManager, /user/userlist, read
p, systemManager, /order/orderlist, read
g, demo, admin
g, demo1, admin
g, kongdy, admin
g, kongdy, systemManager

这里是基于单租户RBAC的鉴权模式

p 开头的为 policy

g 开头的为用户-角色

model.pml文件中matchers字段:请求 r 的 sub 与 g 的用户匹配,匹配到后,减少匹配到的角色中,是否有同时匹配 obj 和 act

可以嵌套角色,默认最多可嵌套10层,但需要注意用户与角色不要存在相同值,否则会拥有该重名角色的权限

p, userManager, /user, write
p, userManager, /user, read
p, userManager, /user, put
p, orderManager, /order, write
p, orderManager, /order, read
p, userManager, /user/userlist, read
p, orderManager, /order/orderlist, readg, admin, userManager
g, admin, orderManager
g, manage, userManagerg, demo, admin
g, demo1, manage

这里可以理解为

demo用户拥有admin角色权限,admin角色继承userManager和orderManager角色,即同时拥有这两个角色的访问控制

demo1用户拥有userManager角色

也可以理解为

demo用户拥有admin角色权限,admin角色继承userManager和orderManager角色,即同时拥有这两个角色的访问控制

demo1用户拥有userManager角色

admin用户拥有userManager、orderManager两个角色

manage拥有userManager角色

理解以上policy后,也就明白了为什么用户名要与角色名称不要重叠的原因

main.go

package mainimport ("fmt""github.com/casbin/casbin/v2"
)func main() {e, err := casbin.NewEnforcer("./model.pml", "./policy.csv")if err != nil {fmt.Println("出错啦", err)return}//基本权限设置CheckPermi(e, "demo", "/user", "read")     //CheckPermi(e, "demo", "/user", "put")CheckPermi(e, "demo", "/user", "write")CheckPermi(e, "demo", "/order", "read")CheckPermi(e, "demo", "/order", "write")CheckPermi(e, "demo", "/user/userlist", "read")CheckPermi(e, "demo", "/user/userlist", "write")CheckPermi(e, "demo", "/order/orderlist", "read")CheckPermi(e, "demo", "/order/orderlist", "write")CheckPermi(e, "demo1", "/user", "read")CheckPermi(e, "demo1", "/user", "write")CheckPermi(e, "demo1", "/user", "put")CheckPermi(e, "demo1", "/order", "read")CheckPermi(e, "demo1", "/order", "write")CheckPermi(e, "demo1", "/user/userlist", "read")CheckPermi(e, "demo1", "/user/userlist", "write")CheckPermi(e, "demo1", "/order/orderlist", "read")CheckPermi(e, "demo1", "/order/orderlist", "write")CheckPermi(e, "admin", "/user", "read")CheckPermi(e, "admin", "/user", "write")CheckPermi(e, "admin", "/user", "put")CheckPermi(e, "admin", "/order", "read")CheckPermi(e, "admin", "/order", "write")CheckPermi(e, "admin", "/user/userlist", "read")CheckPermi(e, "admin", "/user/userlist", "write")CheckPermi(e, "admin", "/order/orderlist", "read")CheckPermi(e, "admin", "/order/orderlist", "write")}func CheckPermi(e *casbin.Enforcer, sub, obj, act string) {ok, err := e.Enforce(sub, obj, act)if err != nil {return}if ok == true {fmt.Printf("%s CAN %s %s\n", sub, act, obj)} else {fmt.Printf("%s CANNOT %s %s\n", sub, act, obj)}
}

常用操作

增加用户角色

e.AddRoleForUser("kongdy", "systemManager")
e.SavePolicy()e.AddRolesForUser("demo1", []string{"systemManager", "admin"})
e.SavePolicy()

增加鉴权规则

e.AddPolicy("admin", "/user", "put")
e.SavePolicy()

删除角色(会将所有拥有该角色的记录均删除)

e.DeleteRole("systemManager")
e.SavePolicy()

基于gorm的权限控制

上面的示例基于文件存储来实现的,当数量上去后,管理起来非常不方便,下面采用数据库来存储数据

import ("fmt""github.com/casbin/casbin/v2"gormadapter "github.com/casbin/gorm-adapter/v2"   // 版本注意与casbin保持一致_ "github.com/go-sql-driver/mysql""github.com/jinzhu/gorm"
)// 统一响应结构体
type Response struct {Code    int         `json:"code"`Message string      `json:"message"`Data    interface{} `json:"data"`
}var Db *gorm.DB
var PO *gormadapter.Adapter
var Enforcer *casbin.Enforcer// 数据库连接及角色规则的初始化,会检查并自动创建 casbin_rule 表
func connect() {dsn := "root:root@(127.0.0.1:3306)/gin_study?charset=utf8&parseTime=True&loc=Local"var err errorDb, err = gorm.Open("mysql", dsn)if err != nil {fmt.Println("connect DB error")panic(err)}// 将数据库连接同步给插件, 插件用来操作数据库PO, _ = gormadapter.NewAdapterByDB(Db)// 这里也可以使用原生字符串方式//Enforcer, _ = casbin.NewEnforcer("model.pml", PO)// 开启权限认证日志// Enforcer.EnableLog(true)// 加载数据库中的策略err = Enforcer.LoadPolicy()if err != nil {fmt.Println("loadPolicy error")panic(err)}
}func main() {connect()//基本权限设置CheckPermi(Enforcer, "demo", "/user", "read")CheckPermi(Enforcer, "demo", "/user", "put")CheckPermi(Enforcer, "demo", "/user", "write")CheckPermi(Enforcer, "demo", "/order", "read")CheckPermi(Enforcer, "demo", "/order", "write")CheckPermi(Enforcer, "demo", "/user/userlist", "read")CheckPermi(Enforcer, "demo", "/user/userlist", "write")CheckPermi(Enforcer, "demo", "/order/orderlist", "read")CheckPermi(Enforcer, "demo", "/order/orderlist", "write")
}func CheckPermi(e *casbin.Enforcer, sub, obj, act string) {res, err := e.Enforce(sub, obj, act)if err != nil {fmt.Printf("出错啦:e=%+v\n, err = %+v\n", e, err)return}if res == true {fmt.Printf("%s CAN %s %s\n", sub, act, obj)} else {fmt.Printf("%s CANNOT %s %s\n", sub, act, obj)}
}

中间件

// casbin middleware 权限认证中间件
func CasbinMiddleWare(enforcer *casbin.Enforcer) gin.HandlerFunc {return func(c *gin.Context) {userName := c.GetHeader("userName")if userName == "" {fmt.Println("headers invalid")c.JSON(200, gin.H{"code":    401,"message": "Unauthorized","data":    "",})c.Abort()return}// 请求的pathp := c.Request.URL.Path// 请求的方法m := c.Request.Method// 这里认证res, err := enforcer.Enforce(userName, p, m)// 这个 HasPermissionForUser 跟上面的有什么区别// EnforceSafe 会验证角色的相关的权限// 而 HasPermissionForUser 只验证用户是否有权限//res = Enforcer.HasPermissionForUser(userName,p,m)if err != nil {fmt.Println("no permission ")fmt.Println(err)c.JSON(200, gin.H{"code":    401,"message": "Unauthorized","data":    "",})c.Abort()return}if !res {fmt.Println("permission check failed")c.JSON(200, gin.H{"code":    401,"message": "Unauthorized","data":    "",})c.Abort()return}c.Next()}
}

相关文章:

  • 游戏引擎学习第239天:通过 OpenGL 渲染游戏
  • Unity Paint In 3D 入门
  • Python线程全面详解:从基础概念到高级应用
  • 鸿蒙生态新利器:华为ArkUI-X混合开发框架深度解析
  • android contentProvider 踩坑日记
  • uniapp 上传二进制流图片
  • 鸿蒙生态:鸿蒙生态校园行心得
  • Windows下Golang与Nuxt项目宝塔部署指南
  • L1-4、如何写出清晰有目标的 Prompt
  • vscode python 代码无法函数跳转的问题
  • 55、Spring Boot 详细讲义(十一 项目实战)springboot应用的登录功能和权限认证
  • 小刚说C语言刷题——1031 温度转化
  • Ubuntu-Linux中vi / vim编辑文件,保存并退出
  • 云账号安全事件分析:黑客利用RAM子账户发起ECS命令执行攻击
  • 联易融科技:以科技赋能驱动经营反转与价值重估
  • 可吸收聚合物:医疗科技与绿色未来的交汇点
  • K8s:概念、特点、核心组件与简单应用
  • 方案精读:华为智慧园区解决方案【附全文阅读】
  • [创业之路-380]:企业法务 - 企业经营中,企业为什么会虚开増值税发票?哪些是虚开増值税发票的行为?示例?风险?
  • SpringCloud组件—Eureka
  • 神二十6个半小时到站
  • 具身智能资本盛宴:3个月37笔融资,北上深争锋BAT下场,人形机器人最火
  • 海南一季度GDP为1904.17亿元,同比增长4.0%
  • 国际货币基金组织:将今年美国经济增长预期下调0.9个百分点至1.8%
  • 深一度|坚守17年,这件事姚明就算赔钱也在继续做
  • 山西公布商标侵权典型案例:一工厂生产价值三百多万假“维达”纸被查