先上链接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(&params)

	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。。。。。。