1、简介:

Casbin是功能强大且高效的开源访问控制库。支持 ACL,RBAC,ABAC 等常用的访问控制模型。官方文档链接:https://casbin.org/docs/zh-CN/overview

image-20201106110406823

2、Golang使用

2.1初始化Casbin

go get -t github.com/casbin/mongodb-adapter

import (
    "github.com/casbin/casbin"
    "github.com/casbin/mongodb-adapter"
)

    mgoAdapter := mongodbadapter.NewAdapter("mongodb://admin:123123123@10.136.104.179:27017/admin")
    mgoEnforcer := casbin.NewEnforcer("/Volumes/liuchen/Go/src/awesomeProject1/test.conf", mgoAdapter)       //casbin.NewEnforcer方法接收两个参数,一个是访问控制模型文件(基于PERM模型,见附录)的路径,一个是权限规则文件的路径,支持数据库和文件。

2.2 访问控制模型文件:

Module File 语法:

[request_definition], [policy_definition], [policy_effect], [matchers][role_definition]##
2.2.1 request_definition
[request_definition]
r = sub, obj, act
sub, obj, act
2.2.2 policy_definition
[policy_definition]
p = sub, obj, act
p2 = sub, act

定义的每一行称为 policy rule, p, p2 是 policy rule 的名字. p2 定义的是 sub 所有的资源都能执行 act

2.2.3 policy_effect

对policy生效范围的定义, 原语定义了当多个policy rule同时匹配访问请求request时,该如何对多个决策结果进行集成以实现统一决策。

[policy_effect]
e = some(where (p.eft == allow))
allowallowp.eftallowdenyallowp.eftallow
2.2.4 matchers

定义了策略匹配者。匹配者是一组表达式。它定义了如何根据请求来匹配策略规则。

[matchers]
m = r.sub == p.sub && r.obj == p.obj && r.act == p.act
2.2.5 role_definition
[role_definition]
g = _, _
g2 = _, _

RBAC角色继承关系的定义。 Casbin 支持 RBAC 系统的多个实例, 例如, 用户可以具有角色及其继承关系, 资源也可以具有角色及其继承关系。 这两个 RBAC 系统不会互相干扰

gg2_, _g

2.3 Go 常用API 基于RBAC

2.3.1添加规则:
mgoEnforcer.AddPolicy("角色1","权限1", "访问规则")
mgoEnforcer.AddPermissionsForUser("角色1","权限1", "访问规则")  // 访问规则可为可选
2.3.2 为用户添加角色
mgoEnforcer.AddRoleForUser("用户1", "角色1")
2.3.3 删除用户
mgoEnforcer.DeleteUser("用户1")
2.3.4 删除权限
mgoEnforcer.DeletePermission("权限1")
2.3.4 获取用户角色
res, err := mgoEnforcer.GetRolesForUser("用户1")
2.3.5 获取用户权限
per := mgoEnforcer.GetPermissionsForUser("用户1")
2.3.6 获取拥有该角色的用户
res, err:=mgoEnforcer.GetRolesForUser("角色1")

2.4 多副本实例一致性问题:

关于集群或多实例一致性问题,官方在主库并未集成,采用应用watcher程序来实现观察者模式。目前官方支持golang watcher程序驱动如下:

image-20201106173425293

下附Redis Watch使用代码:

import (
    "github.com/casbin/casbin"
    "github.com/casbin/casbin/util"
    "github.com/billcobbler/casbin-redis-watcher"
)

func updateCallback(msg string) {
    util.LogPrint(msg)
}

func main() {
    // Initialize the watcher.
    // Use the Redis host as parameter.
    w, _ := rediswatcher.NewWatcher("127.0.0.1:6379")

    // Initialize the enforcer.
    e := casbin.NewEnforcer("examples/rbac_model.conf", "examples/rbac_policy.csv")

    // Set the watcher for the enforcer.
    e.SetWatcher(w)

    // Set callback to local example
    w.SetUpdateCallback(updateCallback)

    // Update the policy to test the effect.
    // You should see "[casbin rules updated]" in the log.
    e.SavePolicy()
}

附录

1、PERM模型
  • Policy: 定义权限的规则
  • Effect: 定义组合了多个 Policy 之后的结果, allow/deny
  • Request: 访问请求, 也就是谁想操作什么
  • Matcher: 判断 Request 是否满足 Policy
2、部分API列表
//获取当前策略中显示的主题列表
allSubjects := e.GetAllSubjects()

//获取当前命名策略中显示的主题列表
allNamedSubjects := e.GetAllNamedSubjects("p")

//获取当前策略中显示的对象列表
allObjects := e.GetAllObjects()

//获取当前命名策略中显示的对象列表
allNamedObjects := e.GetAllNamedObjects("p")

//获取当前策略中显示的操作列表
allActions := e.GetAllActions()

//获取当前命名策略中显示的操作列表
allNamedActions := e.GetAllNamedActions("p")

//获取当前策略中显示的角色列表
allRoles = e.GetAllRoles()

//获取当前命名策略中显示的角色列表
allNamedRoles := e.GetAllNamedRoles("g")

//获取策略中的所有授权规则
policy = e.GetPolicy()

//获取策略中的所有授权规则,可以指定字段筛选器
filteredPolicy := e.GetFilteredPolicy(0, "alice")

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

//获取命名策略中的所有授权规则,可以指定字段过滤器
filteredNamedPolicy = e.GetFilteredNamedPolicy("p", 0, "bob")

//获取策略中的所有角色继承规则
groupingPolicy := e.GetGroupingPolicy()

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

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

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

// 确定是否存在授权规则
hasPolicy := e.HasPolicy("data2_admin", "data2", "read")

//确定是否存在命名授权规则
hasNamedPolicy := e.HasNamedPolicy("p", "data2_admin", "data2", "read")

//向当前策略添加授权规则。 如果规则已经存在,函数返回false,并且不会添加规则。 否则,函数通过添加新规则并返回true
added := e.AddPolicy("eve", "data3", "read")

// 向当前命名策略添加授权规则。 如果规则已经存在,函数返回false,并且不会添加规则。 否则,函数通过添加新规则并返回true
added := e.AddNamedPolicy("p", "eve", "data3", "read")

// 从当前策略中删除授权规则
removed := e.RemovePolicy("alice", "data1", "read")

// 移除当前策略中的授权规则,可以指定字段筛选器。 RemovePolicy 从当前策略中删除授权规则
removed := e.RemoveFilteredPolicy(0, "alice", "data1", "read")

//从当前命名策略中删除授权规则
removed := e.RemoveNamedPolicy("p", "alice", "data1", "read")

//从当前命名策略中移除授权规则,可以指定字段筛选器
removed := e.RemoveFilteredNamedPolicy("p", 0, "alice", "data1", "read")

//确定是否存在角色继承规则
has := e.HasGroupingPolicy("alice", "data2_admin")

//确定是否存在命名角色继承规则
has := e.HasNamedGroupingPolicy("g", "alice", "data2_admin")

// 向当前策略添加角色继承规则。 如果规则已经存在,函数返回false,并且不会添加规则。 如果规则已经存在,函数返回false,并且不会添加规则
added := e.AddGroupingPolicy("group1", "data2_admin")

//将命名角色继承规则添加到当前策略。 如果规则已经存在,函数返回false,并且不会添加规则。 否则,函数通过添加新规则并返回true
added := e.AddNamedGroupingPolicy("g", "group1", "data2_admin")

// 从当前策略中删除角色继承规则
removed := e.RemoveGroupingPolicy("alice", "data2_admin")

//从当前策略中移除角色继承规则,可以指定字段筛选器
removed := e.RemoveFilteredGroupingPolicy(0, "alice")

//从当前命名策略中移除角色继承规则
removed := e.RemoveNamedGroupingPolicy("g", "alice")

//当前命名策略中移除角色继承规则,可以指定字段筛选器
removed := e.RemoveFilteredNamedGroupingPolicy("g", 0, "alice")

参考链接: