先上链接casbin官网
casbin能做什么?
支持多种编程语言Go/Java/Node/PHP/Python/.NET/Rust,一次学习多处运用
Casbin 不能做什么?
- 身份认证 authentication(即验证用户的用户名、密码),casbin只负责访问控制。应该有其他专门的组件负责身份认证,然后由casbin进行访问控制,二者是相互配合的关系。
- 管理用户列表或角色列表。 Casbin 认为由项目自身来管理用户、角色列表更为合适, 用户通常有他们的密码,但是 Casbin 的设计思想并不是把它作为一个存储密码的容器。 而是存储RBAC方案中用户和角色之间的映射关系
快速开始
Casbin使用配置文件来设置访问控制模式。
model.confpolicy.csv
mkdir demo && cd demo && go mod init github.com/51op/go-sdk-demo
go get github.com/casbin/casbin/v2
- 创建model模型文件model.conf
[request_definition]
r = sub, obj, act
[policy_definition]
p = sub, obj, act
[matchers]
m = r.sub == p.sub && r.obj == p.obj && r.act == p.act || r.sub == "root" #只要访问主体是root一律放行。
[policy_effect]
e = some(where (p.eft == allow))
subobjactp.eft
- 创建策略控制文件policy.csv
p, demo , /user, write #demo用户对/user有write权限
p, demo , /order, read #demo用户对/order有read权限
p, demo1 , /user/userlist,read #demo1用户对/user/userlist有read权限
p, demo2 , /order/orderlist,read #demo2用户对/order/orderlist有read权限
- 检查权限
import (
"fmt"
"github.com/casbin/casbin/v2"
gormadapter "github.com/casbin/gorm-adapter/v3"
_ "github.com/go-sql-driver/mysql"
"log"
"testing"
)
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)
}
}
func TestCasBin( t *testing.T) {
e, err := casbin.NewEnforcer("./model.conf", "./policy.csv")
if err !=nil{
log.Fatalf("NewEnforecer failed:%v\n", err)
}
//基本权限设置
CheckPermi(e, "demo", "/user", "read")
CheckPermi(e, "demo", "/order", "write")
CheckPermi(e, "demo1", "/user/userlist", "read")
CheckPermi(e, "demo1", "/order/orderlist", "write")
}
实战项目 参考
勿喷
- 目录结构如下:
dnspod/
├── api
│ ├── casbiniapi.go
│ ├── internal
│ │ └── model
│ │ └── casbin.go
├── config
│ ├── config.json
│ ├── config.yaml
│ └── model.conf
├── common
│ ├── global.go
├── Dockerfile
├── docs
│ ├── docs.go
│ ├── swagger.json
│ └── swagger.yaml
├── go.mod
├── go.sum
├── main.go
├── router
│ ├── handler
│ │ └── func.go
│ └── route.go
configs目录下创建
#此文件存储访问模型
[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 = r.sub == p.sub && ParamsMatch(r.obj,p.obj) && r.act == p.act
api/internal/modelcasbin.go
package model
import (
"dnspod/common"
_ "dnspod/common"
"log"
)
type CasinoModel struct {
PType string `gorm:"column:p_type" json:"p_type" form:"p_type" description:"策略类型"`
RoleId string `gorm:"column:v0" json:"role_id" form:"v0" description:"角色id"`
Path string `gorm:"column:v1" json:"path" form:"v1" description:"api路径"`
Method string `gorm:"column:v2" json:"method" form:"v2" description:"方法"`
}
func(c *CasinoModel) TableName() string {
return "casbin_rule"
}
func ( c *CasinoModel) AddPolicy() error {
if ok,_:=common.CasBin.AddPolicy(c.RoleId,c.Path,c.Method);ok==false{
return common.JsonResponse(100,"增加策略失败")
}
return common.JsonResponse(200,"增加策略成功")
}
- 在common/目录下的global.go文件中增加如下:
func InitCasbinDB() *casbin.Enforcer {
cfg:=Initconfig()
adapter, _ := gormadapter.NewAdapter("mysql", "epai:epai706@tcp(10.10.10.5:3306)/",)
CasBin, _ = casbin.NewEnforcer(cfg.CasBin.FilePath, adapter)
CasBin.AddFunction("ParamsMatch",ParamsMatchFunc)
CasBin.LoadPolicy()
return CasBin
}
func ParamsMatch(fullNameKey1 string,key2 string) bool {
key1 := strings.Split(fullNameKey1, "?")[0]
return util.KeyMatch2(key1,key2)
}
//注册func到casbin
func ParamsMatchFunc(args ...interface{})(interface{},error) {
name1 := args[0].(string)
name2 := args[1].(string)
return ParamsMatch(name1, name2), nil
}
common.InitCasbinDB() //初始化 InitCasbinDB
//Casbin权限认证
authGroup:=router.Group("/api/v1/auth")
{
authGroup.POST("/addPolicy",handler.AddPolicy)
}
//Casbin 权限管理
type CasbinInfo struct {
Path string `json:"path" form:"path"`
Method string `json:"method" form:"method"`
}
type CasbinCreateRequest struct {
RoleId string `json:"role_id" form:"role_id" description:"角色ID"`
CasbinInfos []CasbinInfo `json:"casbin_infos" description:"权限模型列表"`
}
func AddPolicy(c *gin.Context ) {
log.Printf("==========")
var params CasbinCreateRequest
c.ShouldBind(¶ms)
for _, v := range params.CasbinInfos {
log.Println(params.RoleId, v.Path, v.Method)
err := api.AddPolicyApi(params.RoleId, v.Path, v.Method)
if err != nil {
// c.JSON(http.StatusOK,gin.H{
// "res":"bad",
// })
}
}
c.JSON(http.StatusOK,gin.H{
"res":"ok",
})
}
- 在api/目录下创建casbiniapi.go文件
package api
import "dnspod/api/internal/model"
func AddPolicyApi(roleId string, path, method string) error {
p:=model.CasinoModel{
PType: "p",
RoleId: roleId,
Path: path,
Method: method,
}
p.AddPolicy()
return nil
}
最后启动项目
验证
查看mysql库里数据就有了
【关注我】持续更新ing。。。。。。