一、使用数据库存储 policy

使用gorm适配器进行存储

  • 首先引用包
go get github.com/casbin/gorm-adapter
go get github.com/casbin/gorm-adapter/v3
go get github.com/go-sql-driver/mysql
  • 其次给数据库建一个casbin数据库
  • 下面是一个基础用法,详细看注释
package main

import (
	"fmt"
	"github.com/casbin/casbin/v2"
	gormadapter "github.com/casbin/gorm-adapter/v3"
	_ "github.com/go-sql-driver/mysql"

)

func main() {
    a, _ := gormadapter.NewAdapter("mysql", "root:u_password@tcp(127.0.0.1:3306)/casbin",true) // Your driver and data source. 后面的参数true是自动建表
	e, _ := casbin.NewEnforcer("./model.conf", a)
	sub := "alice" // 想要访问资源的用户。
	obj := "data1" // 将被访问的资源。 
	act := "read"  // 用户对资源执行的操作。
	added, err := e.AddPolicy("alice", "data1", "read") // 给数据库添加数据
	fmt.Println(added) 	// 第一次添加成功就为true,第二次就为false,因为已经存在了这个数据
	fmt.Println(err)
	ok, err := e.Enforce(sub, obj, act)

	if err != nil {
		// 处理err
		fmt.Println(err)
	}

	if ok == true {
		// 允许alice读取data1
		fmt.Println("access")
	} else {
		// 拒绝请求,抛出异常
		fmt.Println("not access")
	}

}

输出
/*
  true
  <nil>
  access
*/

下面是数据库之中自动建表的字段

请添加图片描述


二、go实现增删改查操作

// 添加单个角色
added, err := e.AddGroupingPolicy("alice", "data2_admin") // 这就是给alice这个角色添加到data2_admin组
// 需要在model.conf 里面添加 	[role_definition] g = _, _


// 添加多个角色
rules := [][] string {
                []string {"alex", "data1", "read"},
                []string {"mita", "data1", "write"},
                []string {"rivo", "data1", "read"},
                []string {"brooks", "data1", "write"},
        }

areRulesAdded := e.AddGroupingPolicies(rules)

// 类型为g的
added := e.AddNamedGroupingPolicy("g", "alice", "data2_admin")

// 添加多个
rules := [][] string {
                []string {"jack", "data4", "read"},
                []string {"katy", "data4", "write"},
                []string {"leyo", "data4", "read"},
                []string {"ham", "data4", "write"},
        }

areRulesAdded := e.AddNamedGroupingPolicies("g", rules)


removed, err := e.RemoveFilteredGroupingPolicy(0, "alice") // 指定字段删除alice数据,0代表的就是数据库里面的v0字段,当然会删除所有的alice字段,其余的都大同小异,和增加方法差不多
// UpdatePolicy 把旧的策略更新到新的策略
updated, err := e.UpdatePolicy([]string{"alice", "data1", "read"}, []string{"alice", "data3", " read"})	

// UpdatePolicies 将所有的旧策略更新到新策略
updated, err := e.UpdatePolicies([][]string{{"eve", "data3", "read"}, {"jack", "data3", "read"}}, [][]string{{"eve", "data3", "write"}, {"jack", "data3", "write"}})
// GetFilteredPolicy 获取策略中的所有授权规则,我们可以指定字段筛选器。
filteredPolicy := e.GetFilteredPolicy(0, "alice")

// GetNamedPolicy 获取命名策略中的所有授权规则
namedPolicy := e.GetNamedPolicy("p")

// GetFilteredGroupingPolicy 获取策略中的所有角色继承规则,可以指定字段筛选器。
filteredGroupingPolicy := e.GetFilteredGroupingPolicy(0, "alice")

// GetNamedGroupingPolicy 获取策略中的所有角色继承规则。
namedGroupingPolicy := e.GetNamedGroupingPolicy("g")

// HasNamedPolicy 判断这个名字的权限类型是否存在
hasNamedPolicy := e.HasNamedPolicy("p", "data2_admin", "data2", "read")


三、自定义比较函数

我们可以自定义比较函数,其实g匹配规则的内核原理也和这个差不多

// 在函数里面执行这个 KeyMatchFunc 函数
e.AddFunction("my_func", KeyMatchFunc)

// KeyMatch 比较规则,实际就是做了层包装,里面的规则看自己需要做修改
func KeyMatch(key1 string, key2 string) bool {
    i := strings.Index(key2, "*")
    if i == -1 {
        return key1 == key2
    }

    if len(key1) > i {
        return key1[:i] == key2[:i]
    }
    return key1 == key2[:i]
}

// KeyMatchFunc 用一个接口类型封装它
func KeyMatchFunc(args ...interface{}) (interface{}, error) {
    name1 := args[0].(string)
    name2 := args[1].(string)

    return (bool)(KeyMatch(name1, name2)), nil
}

// 现在就可以在 model.conf 里面使用这个函数了 
[matchers]
m = r.sub == p.sub && my_func(r.obj, p.obj) && r.act == p.act