Casdoor的权限检查
Casdoor 的权限检查机制是基于 Casbin 的,参考文档:
简要介绍
所有在同一个组织的用户可以访问该组织下的所有应用,但是有时候需要做一些限制,这里就要用到 权限(permission) 了。
那么 权限(permission) 的作用就是用于控制 用户 能否对 应用 进行某些 操作
最简单的方式就是在 权限(permission) 配置页面新建一个权限,如下图所示:
作为三个要素,用户,应用和操作,在这里是需要配置的:
- 包含用户
- 资源
- 动作
意义也比较简单,就是哪些 用户 可以对哪些 应用 进行哪些 操作
包含角色 也容易理解,一个角色对应多个人,所以这里就是用来控制一组人的。
那上面的模型是什么意思呢,Casdoor 是如何根据这个配置进行权限校验的呢?
ACL 权限控制模型
ACL 权限控制模型应该很熟悉了吧,Linux 上就在使用,这里就不再赘述,参考:
Casbin 的权限控制
Casbin 是一个开源的权限控制库,它支持了多种权限控制模型
Casbin 实施权限规则比较简单,管理员需要列出 主体(subject),对象(object) 和期望允许的 操作(action) 即可:
- subject,主体,比如用户
- object,对象,需要被权限控制的对象
- action,动作,read,write,delete或者其他定义的动作(操作)
管理员需要定义 模型(model) 文件来确定校验条件,Casbin 提供了一个 执行器(Enforcer) 来根据规则定义和模型文件来校验请求。
也就是说 Casbin 权限校验需要三个部分:模型(Model), 校验规则(Policy)和执行器(Enforcer)。
执行器是 Casbin 自带的,可以不必特别关注,只需要知道这件事情就行。下来着重研究模型和校验规则。
哦,对了进行权限校验还需要一个 请求(request)
模型定义
Casbin 里的权限控制模型被抽象成了一个 CONF 文件,基于 PERM metamodel (Policy, Effect, Request, Matchers)
,这个 PERM metamodel 基于 4 个部分 Policy, Effect, Request, Matchers,其描述了 资源 和 用户 之间的关系。
Casbin 里最简单的一个模型,也是默认模型:
1 | [request_definition] |
Request
r = sub, obj, act
定义了请求参数,也就是说请求需要三个部分,subject,object 和 action,通俗点讲就是 访问的用户,访问的对象,访问的方法。
这里其实定义了我们应该提供给权限控制匹配函数的参数名和顺序。
Policy
p = permission, sub, obj, act
定义了模型的访问策略,其实是定义了在策略规则文档中字段名和顺序
这里还有一种定义:p={sub, obj, act, eft}
eft是可以被省略的,eft代表的是策略的结果,比如就是 allow 或者是 deny,如果没有定义的话,读取策略文件的时候就会被忽略,默认会返回 allow
Matcher
m = r.sub == p.sub && r.obj == p.obj && r.act == p.act
请求和策略的匹配规则,这里 r 就是请求(request),p 就是策略(policy)
Effect
e = some(where (p.eft == allow))
就是对策略的结果再次进行条件判断,这里的意思就是只要有一条规则返回的是 allow,那么整个就是 allow
还有这样的定义:e = some(where (p.eft == allow)) && !some(where (p.eft == deny))
就是说有一条是 allow 而且 没有 deny 的情况,整个结果是 allow
这里主要是针对多条匹配规则都匹配上的情况做处理的
在 Casdoor 定义权限控制
定义模型
我们已经了解了模型的定义规则,那么就开始在 Casdoor 上面实际操作一番吧。
模型定义用来针对要控制的 object,访问的 subject 能允许怎样的 action
首先在页面顶部导航栏点击 模型(Model),点击新增:
模型文本这里就填写上面介绍过的模型定义字符串,点击保存&退出
。
定义权限
在页面顶部导航栏点击 权限(permission),点击新增:
permission 其实就是具体的控制权限设置,可以针对多个资源进行控制
其实这里的配置界面只是简化了规则的配置,这个页面的权限其实会转换成类似如下的数据:
1 | p alice data1 read |
代码上
permission 里定义的规则会先转换成 CasbinRule 对象,每一个对象就包含了 Policy 定义的每个字段,之后就会转成如下的字符串:
p, built-in/permission-built-in, built-in/app-built-in/admin, app-built-in, read
执行校验
模型和权限定义好之后,对应被控制的用户访问被控制的应用时,Casdoor 就会进行加载对应模型和权限进行校验,执行这一工作的叫做 Enforcer
关于 Enforcer 的文档:New a Casbin enforcer
代码分析
流程已经分析差不多了,让我们看看代码上是怎么处理的
Casdoor 是在这个函数做权限校验的。用户登陆时候就会调用,当然在任何你想进行权限校验的地方,都可以进行调用。
1 | func CheckAccessPermission(userId string, application *Application) (bool, error) { |
逻辑就是通过 organization 来获取所有的 permission 配置,接下来遍历 permission 中定义的 resource,如果跟当前的应用匹配,那么用这条权限去检查用户是否有对应的权限。
匹配成功之后,调用 getEnforcer 来获取一个执行权限校验的 enforcer。
1 | func getEnforcer(permission *Permission) *casbin.Enforcer { |
getEnforcer 做的工作就是根据 权限(permission)
数据去看有没有定义好的model,有的话使用定义好的模型文本来加载 enforcer,否则使用默认的模型文本:
1 | [request_definition] |
加载模型文本之后,enforcer 就会加载对应 权限(permission)
所对应定义的规则,对应 LoadFilteredPolicy
函数。
这些数据加载完成之后,enforcer 会根据传入的 subject,entity,action,即 用户,应用,操作,来检查权限是否允许
allowed, err = enforcer.Enforce(userId, application.Name, "read")
总结
总结一下,主要有以下核心:
- 理解 Casdoor 的权限是做什么的
- 理解 模型(Model) 以及 模型文本 是如何定义的
- 理解 模型,权限是如何配置的,以及是如何对用户,应用进行控制的
- 理解代码上是如何调用的,可以扩展到其他需要进行权限校验的地方
注意
在代码上新建或者编辑权限(permission)
之后,记得要重新生成一下规则(policy)
,因为不论在界面上是怎样的表现形式,最后都是enforcer通过model text
和policy
来检查request
的
代码如下:
1 | // 更新permission之后需要调用 |