在使用 Casbin 做权限控制时,很多人会把 Model 和 Policy 混在一起理解,结果在配置结构、持久化方式和运行时职责上频繁踩坑。本文按“语法结构”和“存储策略”两条线拆开说明,帮助你判断哪些内容属于固定模型定义,哪些内容才应该交给持久层与 adapter 处理。
Model 语法由哪些部分组成
Casbin 的 Model 配置文件并不是随意拼接的文本,它有明确的结构要求。一个最基本的 Model CONF,至少需要包含以下四个部分:

[request_definition][policy_definition][policy_effect][matchers]
这四部分共同决定了一次权限请求如何被解释、策略字段如何定义、多个策略命中后如何得出最终效果,以及请求与策略之间如何匹配。
如果当前模型使用的是 RBAC,那么除了上述四部分,还需要额外加入 [role_definition]。也就是说,RBAC 并不是替换原有结构,而是在基础模型之上补充角色关系定义。
另外,Model CONF 支持注释,注释以 # 开头,并且会注释整行内容。这一点虽然简单,但在维护多人协作的权限模型时很有用,适合给匹配规则、字段含义和角色关系补充说明。
Casbin 支持的 model 类型可以查看:https://github.com/php-casbin/php-casbin/blob/master/README_CN.md#%E6%94%AF%E6%8C%81%E7%9A%84Models
为什么 Model 只能加载,不能保存
Casbin 对 Model 的处理方式和 Policy 明显不同。Model 只能被加载,不能被保存。
原因并不复杂:在 Casbin 的设计里,Model 被视为非动态组件。它更像是权限系统的判定框架,用来规定语义和匹配方式,而不是在运行时频繁变动的数据。因此官方没有提供把 Model 保存回存储的 API。
换句话说,如果你希望在系统里修改权限规则内容,通常应该调整的是 Policy;如果你连请求定义、策略定义或匹配逻辑都要改,那已经是在改权限模型本身,而不是日常数据更新。
Policy 的持久化由 adapter 负责
Policy 才是 Casbin 中面向持久化的那一层。它的读写细节由适配器 adapter 实现,adapter 可以理解为 Casbin 与具体存储之间的中间层。

在实际使用中,开发者可以调用 adapter 的 LoadPolicy() 方法,从持久层加载 policy 规则;也可以调用 SavePolicy() 方法,把 Policy 规则保存回持久层。
这种分工有两个直接好处:
- 权限模型与规则数据分离,职责更清楚。
- Casbin 主库保持轻量,不把各种存储实现直接塞进核心仓库。
也正因为如此,Casbin 没有把 adapter 的代码放进主库中,而是把持久化能力交给适配层扩展。对使用者来说,这意味着你在选型时需要同时关注两件事:一是 Model 是否适合你的权限场景,二是 adapter 是否满足你的存储需求。
更多说明可参考官方文档:https://casbin.org/docs/en/supported-models









