Casbin 是一个强大的、高效的开源访问控制框架,其权限管理机制支持多种访问控制模型。
通俗来讲就是一个权限管理的框架,把常见的权限管理集成在框架中,使用者只需要根据框架规范就可以很方便的实现相应的权限控制。
Casbin 支持的权限管理如下:
- ACL (Access Control List, 访问控制列表)
- 具有 超级用户 的 ACL
- 没有用户的 ACL: 对于没有身份验证或用户登录的系统尤其有用。
- 没有资源的 ACL: 某些场景可能只针对资源的类型, 而不是单个资源, 诸如
write-article
,read-log
等权限。 它不控制对特定文章或日志的访问。 - RBAC (基于角色的访问控制)
- 支持资源角色的RBAC: 用户和资源可以同时具有角色 (或组)。
- 支持域/租户的RBAC: 用户可以为不同的域/租户设置不同的角色集。
- ABAC (基于属性的访问控制): 支持利用
resource.Owner
这种语法糖获取元素的属性。 - RESTful: 支持路径, 如
/res/*
,/res/: id
和 HTTP 方法, 如GET
,POST
,PUT
,DELETE
- 拒绝优先: 支持允许和拒绝授权, 拒绝优先于允许。
- 优先级: 策略规则按照先后次序确定优先级,类似于防火墙规则。
Model 概念
Model 相当于框架的配置文件,如我想在系统里有可能实现 是ALC
或者 RBAC
,应该如何告诉 Casbin 框架,我实现的是那种类型的权限控制呢?答案就是通过 Mdoel 来配置。
如果要掌握 Casbin 框架,那就需要对 Model 有一个比较深入的理解。接下来就讲解 Model 的一些语法。
request 定义
此处定义主要作用于验证时,应该验证哪些项,此处的配置名称和顺序是可以不固定的,你可以随意更改,但是需要与配置的其他部分配合上才可以,为了方便维护,建议按照官网的一些通用配置去配置。如上述配置,我这边就可以认为想要验证:用户角色,路由,方法。
定义方式如下(具体含义,请参考文档):
[request_definition]
r = sub, obj, act
Policy 定义
Policy (策略),主要是配置系统用户所拥有权限的规则,这里仅仅是规则的配置,数据是存在文件或数据库里的,存储的格式就是按照此配置进行存储的,存储是框架里处理好的,我们只需要调用相关方法即可。
如我想给张三加一条 /zhangsan get 的访问权限数据库就会存入下列信息 (数据库格式并非如此,为了方便讲解取了语义化的名字,实际操作中无需关心数据结构,casbin 已经在框架层面做了处理)
sub | obj | act |
---|---|---|
张三 | /zhangsan | get |
当张三来请求 /zhangsan 资源的时候,我们可以通过前面配置的 request 与 这条记录进行对比,如果匹配的上就通过,匹配不上就提示无权访问的信息。匹配操作也是框架里有相关方法,我们只需要之道整个流程即可。
定义方式如下(具体含义,请参考文档):
[policy_definition]
p = sub, obj, act
Policy effect 定义
Policy effect 主要用于一些多个匹配结果的处理,比如,我张三有两个 /zhangsan 的访问权限,且一个是允许访问,一个是不允许访问,那最终是否允许张三访问 /zhangsan 的资源,就是通过 Policy effect 来处理的
定义方式如下(具体含义,请参考文档):
[policy_effect]
e = some(where (p.eft == allow))
匹配器(matchers)
我们前面定义了 request_definition和 policy_definition,他们们之间是如何进行匹配的?就是通过匹配器来确定的
定义方式如下(具体含义,请参考文档):
[matchers]
m = r.sub == p.sub && r.obj == p.obj && r.act == p.act
角色定义(role_definition)
角色定义是 RBAC
特有的一个配置项,用来定义角色的配置规则。
定义方式如下(具体含义,请参考文档):
[role_definition]
g = _, _
[matchers]
m = g(r.sub, p.sub) && r.obj == p.obj && r.act == p.act
这里需要结合 matchers 一起来说明,role_definition 可以看做定义了一个角色验证的函数,上述示例就是 g, 后面的两个 _ 则是对应函数传入的参数,这个 g 函数的使用就是在**匹配器(matchers)**中使用的。
上述配置即为,请求来了我需要拿 请求(r)中定义的 obj 和 act 去匹配策略(policy)中的 obj,act。 如果 r.obj==p.obj 并且 r.act == p.act 能匹配的到则说明有相关权限,请求放行,否则拒绝请求。
policy 如何存储
上个章节,我们只说到了 policy 的定义规则,那具体需要匹配的数据是用怎么样的方式来存储的呢。
policy 默认是通过 csv 文件存储, 可以通过 适配器 来扩展你自己的存储方式。
如何使用
Casbin使用配置文件来设置访问控制模式。
它有两个配置文件, model.conf
和 policy.csv
。 其中, model.conf
存储了访问模型, policy.csv
存储了特定的用户权限配置。 Casbin的使用非常精炼。 基本上,我们只需要一个主要结构:enforcer。 当构建这个结构时, model.conf
和 policy.csv
将被加载。换句话说,要新建一个Casbin执行器,你必须提供一个Model和一个Adapter。
import (
"log"
"github.com/casbin/casbin/v2"
"github.com/casbin/casbin/v2/model"
xormadapter "github.com/casbin/xorm-adapter/v2"
_ "github.com/go-sql-driver/mysql"
)
// 使用 MySQL 数据库初始化一个 Xorm 适配器
a, err := xormadapter.NewAdapter("mysql", "mysql_username:mysql_password@tcp(127.0.0.1:3306)/casbin")
if err != nil {
log.Fatalf("error: adapter: %s", err)
}
m, err := model.NewModelFromString(`
[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
`)
if err != nil {
log.Fatalf("error: model: %s", err)
}
e, err := casbin.NewEnforcer(m, a)
if err != nil {
log.Fatalf("error: enforcer: %s", err)
}
你可能还会关心的一些东西
关于 RBAC
角色层次
我们都知道 RBAC
一般都会涉及到角色层次,如果 alice
具有 role1
, role1
具有 role2
,则 alice
也将拥有 role2
并继承其权限。
角色层次有层数限制,默认为 10 也可以自己指定。
如何区分用户和角色
在RBAC中,Casbin不对用户和角色进行区分。 它们都被视为字符串
总结
这里基本上将 Casbin 一些基础概念和用法进行了说明,Casbin 作为一款流行的框架功能还是十分强大的。我们可以根据配置,组合出各种想要的权限控制。
在上述的介绍中,我们都只定理了 sub, obj, act 如果想增加对域名的控制应该如何做呢?文末会放一个验证域名的 RBAC 基础项目, 结合项目与本文,相信你会对 Casbin 有一个更加深入的理解。