Casbin配置文件详解,结合RBAC模型设计权限、角色、用户业务逻辑
[request_definition]
r = sub, obj, act
[policy_definition]
p = sub, obj, act, eff
[role_definition]
g = _, _
[policy_effect]
e = some(where (p.eft == allow)) && !some(where (p.eft == deny))
[matchers]
m = g(r.sub, p.sub) && keyMatch2(r.obj, p.obj) && r.act == p.act
[request_definition]用来定义一次请求的参数结构,也就是完成一次鉴权需要哪些字段
举例:"roleId", "/data/resource", "GET"。
[policy_definition]用来定义“策略(Policy)表”这一行数据的数据结构
举例:p, roleName, /data/resource, GET, allow。
[role_definition]用来定义“角色(RBAC)”关系,第一个参数是“成员”,第二个参数是“角色”
举例:g, alice, dev , g, alice, ops,用户与角色是多对多的关系。
[policy_effect]用来定义权限拒绝策略,
e = some(where (p.eft == allow)) && !some(where (p.eft == deny)),意思是只要有一条 deny 命中,就拒绝;只有在“有任意一条 allow 且没有 deny”的情况下,才允许放行。
[matchers]用来定义策略匹配逻辑,m = g(r.sub, p.sub) && keyMatch2(r.obj, p.obj) && r.act == p.act,意思是一条请求是否被允许,请求中的用户 r.sub,拥有策略中定义的角色 p.sub,keyMatch2匹配url的带参数路径,请求的操作必须和策略中定义的操作完全一致,才允许放行。
r :request 的缩写,代表一次访问请求
p :policy 的缩写,代表一行权限策略
g :group 的缩写,代表权限分组
m :matcher 的缩写,代表如何匹配权限策略
| 字段 | 含义 | 说明 |
|---|---|---|
| sub | subject | 访问主体(用户 / 角色 / 客户端 ID 等) |
| obj | object | 访问对象(资源、URL、API、文件路径等) |
| act | action | 操作行为(GET / POST / PUT / DELETE 等) |
| eff | effect | 策略生效结果(通常是 allow 或 deny) |
全量删插(本地内存与持久化同步)
Casbin 的 Enforcer 在内存里维护了一份策略镜像,同时靠 Adapter(如数据库)持久化存储。
- 删:调用类似清除全量策略的接口时,会先清内存,再通过 Adapter 删掉存储介质(DB/文件)里的所有规则。
- 插:随后批量写入新策略,会同时写进内存模型与底层存储,保证两者一致。
- 关键点:这一步默认只发生在当前这个 Enforcer 实例上,别的节点完全感知不到,它们的内存里还是旧策略。
Watcher(多节点广播通知)
在分布式/多实例部署时,A 节点全量删插了,B、C 节点并不知道,会继续用旧策略鉴权,导致结果不一致。Watcher 就是用来解决这个问题的“消息喇叭”:
- 原理:基于发布订阅(如 Redis Pub/Sub、etcd、Kafka 等)。当前节点执行
SavePolicy()等变更操作时,Casbin 会自动调用Watcher.Update()往消息通道发一条信号(“策略变了!”)。 - 接收方动作:其他节点的 Watcher 收到信号后,触发预设的回调函数,通常就是执行
LoadPolicy(),从 DB 重新全量拉取策略覆盖本地内存,从而达到集群最终一致。
缓存清理(CachedEnforcer 的命中失效)
如果用的是 CachedEnforcer,它会把 (sub, obj, act)的鉴权结果缓存起来,避免每次都遍历规则,提升性能。
-
问题:全量删插后,旧缓存全部失效了,如果没清缓存,鉴权还会命中错误的旧结果。
-
机制:
- 自动清理:通过当前实例正常增删改策略(如
AddPolicy)时,CachedEnforcer 会自动失效相关缓存条目。 - 手动清理:全量操作或收到 Watcher 通知重新
LoadPolicy()时,通常需要显式调用InvalidateCache()清空全部缓存,或依赖重新加载时内部清空,确保下次鉴权重新计算并从最新策略里匹配。
- 自动清理:通过当前实例正常增删改策略(如
三者串联的完整链路
管理员在节点 A 执行全量删插 → A 的内存与 DB 更新 → A 的 Watcher 发通知 → 节点 B/C 收到信号 → 各自触发回调执行 LoadPolicy()从 DB 重载内存 → 各自执行缓存清理失效旧结果 → 后续所有鉴权基于最新策略重新计算,达成一致性。
引用官方资料:https://casbin.apache.org/zh/docs/function
| keyMatch | 像/alice_data/resource1这样的URL路径 |
像/alice_data/*这样的URL路径或*模式 |
keymatch_model.conf/keymatch_policy.csv |
|---|---|---|---|
| keyMatch2 | 像/alice_data/resource1这样的URL路径 |
像/alice_data/:resource这样的URL路径或:模式 |
keymatch2_model.conf/keymatch2_policy.csv |
| keyMatch3 | 像/alice_data/resource1这样的URL路径 |
像/alice_data/{resource}这样的URL路径或{}模式 |
https://github.com/casbin/casbin/blob/277c1a2b85698272f764d71a94d2595a8d425915/util/builtin_operators_test.go#L171-L196 |
| keyMatch4 | 像/alice_data/123/book/123这样的URL路径 |
像/alice_data/{id}/book/{id}这样的URL路径或{}模式 |
https://github.com/casbin/casbin/blob/277c1a2b85698272f764d71a94d2595a8d425915/util/builtin_operators_test.go#L208-L222 |
| keyMatch5 | 像/alice_data/123/?status=1这样的URL路径 |
像/alice_data/{id}/*这样的URL路径,{}或*模式 |
https://github.com/casbin/casbin/blob/1cde2646d10ad1190c0d784c3a1c0e1ace1b5bc9/util/builtin_operators_test.go#L485-L526 |
| regexMatch | 任何字符串 | 一个正则表达式模式 | keymatch_model.conf/keymatch_policy.csv |
| ipMatch | 像192.168.2.123这样的IP地址 |
像192.168.2.0/24这样的IP地址或CIDR |
ipmatch_model.conf/ipmatch_policy.csv |
| globMatch | 像/alice_data/resource1这样的路径样式路径 |
像/alice_data/*这样的glob模式 |
https://github.com/casbin/casbin/blob/277c1a2b85698272f764d71a94d2595a8d425915/util/builtin_operators_test.go#L426-L466 |
| keyGet | 像/proj/resource1这样的URL路径 |
像/proj/*这样的URL路径或*模式 |
\ |
| keyGet2 | 像/proj/resource1这样的URL路径 |
a URL path or : pattern like /proj/:resource |
在模式中指定的键名 |
| keyGet3 | 像/proj/res3_admin/这样的URL路径 |
像/proj/{resource}_admin/*这样的URL路径或{}模式 |
在模式中指定的键名 |

浙公网安备 33010602011771号