权限模型

casbin 使用的是 PERM(Policy, Effect, Request, Matchers) 来进行权限控制的。这四种实体之间相互作用的结果就可以用来进行授权的操作。

requestpoliciesrequest

下图就包含四个实体之间是如何作用产生权限访问的

request match effecteffectpolicy_effect

模型定义

下面的内容就是一个简单的权限控制中四个实体的定义文件中的内容, 文件名为 auth_model.conf

[request_definition]
r = sub, obj, act

[policy_definition]
p = sub, obj, act

[policy_effect]
e = some(where (p.eft == allow))

[matchers]
m = r.sub == p.sub && r.obj == p.obj && r.act == p.act
request

定义中的 matchers 则表示匹配的策略,此例中表示的请求的每个字段和策略的每个字段都一一对应。

request
p, alice, data1, read
p, bob, data2, write

实例介绍

实例1

此例子较为简单,就是按照上述介绍的例子进行数据操作的。

package main

import (
	"fmt"
	"github.com/casbin/casbin"
)

func main() {
	e:= casbin.NewEnforcer("/path/to/auth_model.conf", "/path/to/policy.csv")
	ok := e.Enforce("bob", "data2", "write")
	fmt.Println("enforce result is ", ok) // enforce result is true
}

实例2

这个实例不仅包含用户的权限定义,还涉及到角色的定义,而且用户和角色还都有 domain 的限制。

auth_model_with_domain.conf 如下

[request_definition]
r = sub, dom, obj, act

[policy_definition]
p = sub, dom, obj, act

[role_definition]
g = _, _, _

[policy_effect]
e = some(where (p.eft == allow))
[matchers]
m = g(r.sub, p.sub, r.dom) && r.dom == p.dom && keyMatch(r.obj, p.obj) && (r.act == p.act || p.act == "*")

policy_with_domain.csv 如下

p, admin, zhihu, /*, *
p, anonymous, zhihu, /login, *
p, member, zhihu, /logout, *
p, member, zhihu, /member/*, *
g, test, admin, zhihu
requestpolicydomrole_definition_, _, __
// GenerateGFunction is the factory method of the g(_, _) function.
func GenerateGFunction(rm rbac.RoleManager) func(args ...interface{}) (interface{}, error) {
	return func(args ...interface{}) (interface{}, error) {
		name1 := args[0].(string)
		name2 := args[1].(string)

		if rm == nil {
			return name1 == name2, nil
		} else if len(args) == 2 {
			res, _ := rm.HasLink(name1, name2)
			return res, nil
		} else {
			domain := args[2].(string)
			res, _ := rm.HasLink(name1, name2, domain)
			return res, nil
		}
	}
}
g_
gg
domianzhihudomain(可以理解为应用)admindomainadmin

实例代码如下

package main

import (
	"fmt"
	"github.com/casbin/casbin"
)

func main() {
	e := casbin.NewEnforcer("/paht/to/auth_model_with_domain.conf", "/path/to/policy_with_domain.csv")
	ok := e.Enforce("test", "zhihu", "/login", "admin")
	fmt.Println("enforce result is ", ok) // enforce result is true
}