首先安装
go get github.com/casbin/casbin/v2
文件模式使用
Casbin使用配置文件来设置访问控制模型
它有两个配置文件,
model.conf
和policy.csv
。
其中,
model.conf
存储了我们的访问模型,而
policy.csv
存储的是我们具体的用户权限配置。
Casbin
的使用非常精炼。 基本上,我们只需要一种主要的结构:enforcer 当构造这个结构的时候,model.conf
和policy.csv
将会被加载。
model.conf
# Request definition
[request_definition]
r = sub, obj, act
# Policy definition
[policy_definition]
p = sub, obj, act
# Policy effect
[policy_effect]
e = some(where (p.eft == allow))
# Matchers
[matchers]
m = r.sub == p.sub && r.obj == p.obj && r.act == p.act
policy.csv
p, alice, data1, read
p, bob, data2, write
Main.go
package main
import (
"fmt"
"github.com/casbin/casbin/v2"
"log"
)
func main() {
e, err := casbin.NewEnforcer("./model.conf", "./policy.csv")
if err != nil {
log.Fatal(err)
}
sub1 := "alice"
obj1 := "data2"
act1 := "read"
ok, err := e.Enforce(sub1, obj1, act1)
if err != nil {
fmt.Println(err)
}
if ok {
fmt.Println(sub1, "通过!")
} else {
fmt.Println(sub1, "不通过")
}
sub2 := "bob"
obj2 := "data2"
act2 := "write"
ok2, err := e.Enforce(sub2, obj2, act2)
if err != nil {
fmt.Println(err)
}
if ok2 {
fmt.Println(sub2, "通过!")
} else {
fmt.Println(sub2, "不通过")
}
}
➜ casbin go run main.go
alice 不通过
bob 通过!
数据库中使用Casbin
这里使用的是casbin提供的适配器
我使用的是gorm的adapter https://github.com/casbin/gorm-adapter
Gorm Adapter 是 Casbin 的 Gorm 适配器。有了这个库,Casbin 可以从 Gorm 支持的数据库加载策略或将策略保存到它。
INSTALL:
go get github.com/casbin/gorm-adapter/v3
基于官方支持的数据库,目前支持的数据库有:
- MySQL
- PostgreSQL 数据库
- SQL Server 数据库服务器
- Sqlite3
这里我们在本地使用 docker 启动一个本地的数据库
docker run -d --name mysql_container -e MYSQL_ROOT_PASSWORD=123 -p 3306:3306 mysql:latest
创建一个 casbin_db
用来测试
package main
import (
"fmt"
"github.com/casbin/casbin/v2"
gormadapter "github.com/casbin/gorm-adapter/v3"
_ "github.com/go-sql-driver/mysql"
"log"
)
func main() {
// Initialize a Gorm adapter and use it in a Casbin enforcer:
// The adapter will use the MySQL database named "casbin".
// If it doesn't exist, the adapter will create it automatically.
// You can also use an already existing gorm instance with gormadapter.NewAdapterByDB(gormInstance)
a, _ := gormadapter.NewAdapter("mysql", "root:123@tcp(127.0.0.1:3306)/casbin_db", true) // Your driver and data source.
e, _ := casbin.NewEnforcer("./model.conf", a)
// Or you can use an existing DB "abc" like this:
// The adapter will use the table named "casbin_rule".
// If it doesn't exist, the adapter will create it automatically.
// a := gormadapter.NewAdapter("mysql", "mysql_username:mysql_password@tcp(127.0.0.1:3306)/abc", true)
added, _ := e.AddPolicy("alice", "data1", "read")
fmt.Println("添加新的policy!", added)
// Load the policy from DB.
_ = e.LoadPolicy()
// Check the permission.
enforce, err := e.Enforce("alice", "data1", "read")
if err != nil {
log.Fatal(err.Error())
}
fmt.Println("校验结果", enforce)
// Modify the policy.
// e.AddPolicy(...)
// e.RemovePolicy(...)
// Save the policy back to DB.
_ = e.SavePolicy()
}
这里如果数据表不存在的话,会报错!
gormadapter.NewAdapter
传入一个true,表示适配器自动帮你创建表!named "casbin_rule".
可以看到将policy 同步到了数据库中!并且 同步的Enforce
校验就通过了!
而且他内部自动会帮我们查询是不是有重复的policy!如果有add就返回false (下图展示了第二次执行的结果!)
数据库中casbin的CRUD
看文档就行
https://casbin.org/zh/docs/management-api
自定义Mathers 函数
https://casbin.org/zh/docs/function#matchers中的函数
本身内部就有很多内置函数!
我们可以这里重点是看如何自定义函数
首先准备您的函数。 它接受一些参数,然后返回一个布尔类型:我们自定义用在obj资源对象的判断只要为data1 就放过!
func KeyMatch(key1 string, key2 string) bool {
fmt.Println(key1, key2)
return key1 == "data1"
}
然后用 interface{}
类型的接口包装它:
func KeyMatchFunc(args ...interface{}) (interface{}, error) {
name1 := args[0].(string)
name2 := args[1].(string)
return (bool)(KeyMatch(name1, name2)), nil
}
最后,在Casbin的执行者(enforcer)中注册这个函数:
e.AddFunction("KeyMatchFunc", KeyMatchFunc)
现在,您可以在您的模型CONF中像这样使用这个函数:
[matchers]
m = r.sub == p.sub &&KeyMatchFunc(r.obj,p.obj)&& r.act == p.act
完整代码
package main
import (
"fmt"
"github.com/casbin/casbin/v2"
gormadapter "github.com/casbin/gorm-adapter/v3"
_ "github.com/go-sql-driver/mysql"
"log"
)
func KeyMatch(key1 string, key2 string) bool {
return key1 == "data1"
}
func KeyMatchFunc(args ...interface{}) (interface{}, error) {
name1 := args[0].(string)
name2 := args[1].(string)
return (bool)(KeyMatch(name1, name2)), nil
}
func main() {
a, _ := gormadapter.NewAdapter("mysql", "root:123@tcp(127.0.0.1:3306)/casbin_db", true) // Your driver and data source.
e, _ := casbin.NewEnforcer("./model.conf", a)
e.AddFunction("KeyMatchFunc", KeyMatchFunc)
_ = e.LoadPolicy()
enforce, err := e.Enforce("alice", "data1", "write")
if err != nil {
log.Fatal(err.Error())
}
fmt.Println("校验结果", enforce)
_ = e.SavePolicy()
}
Model.conf
# Request definition
[request_definition]
r = sub, obj, act
# Policy definition
[policy_definition]
p = sub, obj, act
# Policy effect
[policy_effect]
e = some(where (p.eft == allow))
# Matchers
[matchers]
m = r.sub == p.sub && KeyMatchFunc(r.obj,p.obj) && r.act == p.act
评论区