Casbin 权限管理
RBAC 和 Casbin 的关系?
RBAC
大家都知道是一种访问控制模型, Casbin
实现了这个模型,并且还实现了其他很多种访问控制模型,如 ABAC
模型。
Casbin 解决了什么问题?
无需自己从零开始做一套访问控制系统,比如为用户添加角色,为角色添加权限等等接口都已经实现了。这套框架被多种语言实现,并且有多种存储适配器。
Casbin 中的概念和 RBAC 的对应关系?
RBAC
中的概念很简单,很容易理解,这里再赘述一下:角色,用户,权限。这三者组合来判断是否能形成对某一资源拥有访问资格。
Casbin
中的概念虽然比较多(因为这一套框架还要兼容其他的访问控制模型),但是仔细看下去,也是比较容易理解的。
以张三读取文章接口为例
RBAC
的鉴权流程:先看张三的所有身份,再看这些身份下是否拥有读取文章接口的权限。
Casbin
的鉴权流程:将张三读取文章接口,抽取三个要素。
第一,操作对象(sub
):张三
第二,动作(act
):读取
第三,资源(obj
):文章接口
将这三要素组合成一组请求 r
,拿着这组请求和已有的策略 p
,去某个列表里按某种匹配规则 m
进行匹配,匹配后的结果传入到 影响
e
中,看是否通过。(别急,下面有解释)。
以上涉及到了几个 Casbin
的重要概念, sub
, act
, obj
, r
, p
, m
, e
。其中 sub
可以是单用户,也可以是角色。其中 p
, m
, e
,相对于 RBAC
模型中我们可能很少遇到。
下面将对以上概念进行解释。
r:请求,由上述三要素组成,格式与=p=一致。可以理解为入口函数。
p:策略=
{sub,obj,act}
,会有一个策略列表(可以简单地理解为等同于 RBAC 中角色和权限的关系表)。通常我们如果仅用RBAC
的话,理解到这里就可以了,后面其实还可以有一个参数,可以简单地理解为禁用(即该操作对象不能操作此资源),黑名单,表示这一组策略被拉黑或者通过,默认为通过。
m:
m
解决的是p
和r
如何进行匹配的问题,是匹配规则,仅返回是否匹配中 。可以理解为如何找到策略列表中对应的规则。比如在此项中,我们可以加入超级管理员的角色的匹配规则,即使没有匹配中常规规则,但如果你是超级管理员的话,也默认为匹配中了。
e:影响。仅做最终对匹配结果后的处理,即最终由这里返回是否通过。只可能有四种(官网有)。可以理解为最后的判断规则。为什么会有这个呢?按道理来说仅有
m
就够了啊?
实际上还是因为上面说过的原因,因为 Casbin
做的不仅是简单 RBAC
,在其他或者更高阶的 RBAC
中,可能会出现有一条策略匹配中了,同时也还匹配上了另外一条策略,但是后一条策略表达的是该用户不能使用此资源,问题就来了,一条允许,一条不允许,那到底是通不通过呢?这时 e
就发挥了作用,你既可以在此项设定所有策略都通过即为通过,也可以设定为有一条通过即为通过。
没有涉及到的概念:角色域。g=用户,角色。这个是用于多租户(多商户)模型的权限控制系统,这里不表。
其他概念和我的经验?
先简单了解一下,做的过程中大致流程和概念及要注意的点,这些清楚后我们就只是调用接口的事了。
两个文件
Casbin 官网中可以看到,初始化时,涉及到了两个文件,一个是模型配置文件 model.conf
,一个是策略文件。
模型文件中,可以定制上述概念的各种组合,比如说 m
中的超级管理员, e
中的到底通不通过问题,别担心,这个或许真的不用存到数据库中,一般定下来就不会动了的。
策略文件,我们就还是算了吧,存储到数据库中,更方便我们管理, Casbin
中有各种存储适配器,我使用的是 grom
的适配器。
注意点
-
在官网中,
Casbin
明确指出,用户表和角色表,应当由项目自己管理,Casbin
只做权限控制。 -
当我们使用
grom
适配器时,初始化Casbin
的时候,会默认创建一张表casbin_rules
,这里面可以存储用户和角色的关系,角色和权限的关系。(这里只说使用Casbin
的RBAC
模型) -
上两点可以得知,用户表,角色表,权限表,我们无论从业务角度还是
Casbin
的限制,都应该我们自己来创建管理。 -
官方文档中,会存在一些错误,有时候我们还是需要读一下
Casbin
和适配器的源码,究竟该如何使用这些接口,甚至说看这些接口有没有。一定要注意Casbin
和适配器的版本,不然可能跟文档对不上。 -
Casbin
为了性能考虑,会将一些数据载入内存中。所以,当项目重启时,一定要记得将casbin_rules
那张表载入到内存中去,即初始化Casbin
时,调用LoadPolicy()
。 -
在我们删除或修改用户,角色,权限时,记得想一下,
casbin_rules
那张表需不需要动呢?如果要动,可以去官网文档中找到对应接口。 -
我的实践,在
casbin_rules
中,角色和用户,我均只存储角色 id 和用户 id ,角色和权限的对应关系中,角色我存 id,权限通常是路由地址,因为检查权限通常是读多写少,这样做的好处是请求来时可以直接通过路由地址和用户 id 检验权限,不用自己再到数据库中查到路由地址 id 后再去查权限。注意:
因为
Casbin
获取用户下的所有权限,和获取角色下的所有权限使用的是同一个接口(在数据层面均当成一个普通字符串处理),所以存储角色 id,最好加一个前缀或后缀。这样可以避免你传入一个用户 id,它取出了一个和你给的用户 id 一样的角色 id,拥有的权限。