Casbin 的 Model 和 Policy:Model 初始化与加载方式详解

季宁
季宁
发布时间:2026-08-25| 76人浏览过
原创

前言

在使用 Casbin 时,很多人知道要写 Model,却不一定清楚它除了读配置文件,还能从字符串或运行时定义中加载。本文把几种常见写法按使用场景拆开说明,再补上空 Model 的后续加载方式,方便你根据配置来源、维护成本和灵活性判断该采用哪一种。

在使用 Casbin 做权限控制时,Model 决定了请求、策略、角色继承和匹配规则怎样组织。很多人刚上手时只会照着示例加载一个 model.conf,但一旦配置来自数据库、需要运行时拼装,或者要把初始化和加载拆开,常见写法就不止一种了。下面按实际开发里的几个问题来整理:先看 Model 有哪些加载入口,再看空 Model 的后续操作方式,方便你根据配置来源和维护成本选择合适方案。

Model 怎么初始化

Casbin 的 Model 常见有三种加载方式:

Casbin Model 三种初始化方式对比插画
Casbin Model 的三种加载入口用专栏式卡片对比文件、字符串和动态定义三种 Model 初始化方式,以及各自更适合的配置来源。
  • 从文件读取
  • 从字符串加载
  • 动态添加定义

这三种方式本质上都是在构建同一份 Model,只是配置来源不同。项目里最常见的是文件方式;如果配置保存在数据库,字符串方式更直接;如果需要在代码里按条件拼装规则,则更适合动态添加。

从文件加载:最常见的接入方式

如果 Model 已经写在配置文件里,初始化时直接传入文件路径即可。这种方式结构最清晰,也最适合固定权限模型的项目。

// 初始化 model
$m = Enforcer::newModel("path/to/model.conf", "");
// 创建一个 enforcer。
$e = new Enforcer($m);

也可以进一步简化,在初始化 Casbin 决策器时直接传入 Model 文件路径:

$e = new Enforcer("path/to/model.conf");

如果你的权限规则长期稳定、需要和代码分开维护,优先考虑这种方式。它的好处是配置文件独立、可读性高,团队成员也更容易定位请求定义、策略定义和匹配表达式分别写在哪里。

从字符串加载:适合数据库中的配置

有些系统会把 Model 配置存进数据库,或者在后台管理页面里维护。这时不需要先落盘为文件,直接读取文本并交给 Casbin 加载即可。

$text = <<<EOT
[request_definition]
r = sub, obj, act

[policy_definition]
p = sub, obj, act

[role_definition]
g = _, _

[policy_effect]
e = some(where (p.eft == allow))

[matchers]
m = g(r.sub, p.sub) && r.obj == p.obj && r.act == p.act
EOT;

// 使用字符串初始化 model
$m = Enforcer::newModel($text);

// 创建一个 enforcer。
$e = new Enforcer($m);

这类写法适合配置来源灵活的场景,尤其是多租户系统、在线配置中心,或者需要按环境切换权限模型的项目。这里的核心不是“字符串”本身,而是你可以把 Model 作为数据来管理,而不必绑定到某个固定文件。

什么时候用动态加载

如果你不想提前准备完整的配置文件,也不想维护一大段 Model 文本,可以先创建空 Model,再逐项补充定义。这样做更适合需要按程序逻辑拼装配置的场景。

// 初始化 model
$m = Enforcer::newModel();
$m->addDef("r", "r", "sub, obj, act");
$m->addDef("p", "p", "sub, obj, act");
$m->addDef("g", "g", "_, _");
$m->addDef("e", "e", "some(where (p.eft == allow))");
$m->addDef("m", "m", "g(r.sub, p.sub) && r.obj == p.obj && r.act == p.act");

// 创建一个 enforcer。
$e = new Enforcer($m);

这里的 addDef 是关键:它允许你分别添加请求定义、策略定义、角色定义、策略效果和匹配器。相比直接加载整段文本,动态方式更适合在代码中组合不同规则,或者在某些字段需要按条件生成时使用。

不过从维护角度看,动态添加的可读性通常不如配置文件。规则一旦变复杂,排查问题时就要回到代码里逐项确认,因此它更适合“确实需要动态构建”的情况,而不是日常默认选择。

空 Model 还能怎么用

除了在初始化阶段一次性写完定义,Casbin 也支持先创建一个空 Model,再决定后续如何加载内容:

空 Model 后续加载方式示意插画
先建空 Model,再决定加载来源把“先创建空 Model,再决定如何填充”的思路拆成步骤卡,突出。
$m = Enforcer::newModel();

有了空 Model 之后,可以根据实际来源选择不同加载方法:

// 从文件加载
$m->loadModel($path);
// 从字符串加载
$m->loadModelFromText($text);
// 动态加载
$m->addDef("r", "r", "sub, obj, act");

这说明 Model 的“创建”和“填充”可以拆成两步。这样做的价值在于,代码结构会更灵活:例如先完成对象初始化,再由不同模块决定从文件、数据库还是运行时参数中补齐定义。

如果你的应用有统一的启动流程,或者要把权限模块封装进框架组件,这种拆分方式会比“初始化时一次传完所有内容”更方便管理。

三种方式该怎么选

实际项目中可以直接按配置来源来判断:

  • 配置固定、希望清晰易维护:用文件加载。
  • 配置保存在数据库或远程配置中心:用字符串加载。
  • 规则需要在代码里按条件拼装:用动态加载。

如果只是普通权限系统,文件方式往往已经足够;只有当 Model 本身变成“可变配置”时,字符串或动态方式的价值才会明显提升。换句话说,三种写法不是能力高低之分,而是适配不同的配置管理方式。

免责声明:本文内容仅供参考,不代表本站观点。转载或引用请注明出处。

Python 相关产品和应用

全部下载
Selenium

Selenium

4.51.0 · Windows

用于浏览器自动化和 Web 测试的 Python 工具。

scikit-learn

scikit-learn

1.9.1 · Windows

常用 Python 机器学习算法与模型评估工具库。

Black

Black

26.10.1 · Windows

强调一致性的 Python 自动代码格式化工具。

Ruff

Ruff

0.17.1 · macOS

由 Rust 编写的高速 Python 代码检查和格式化工具。

pytest

pytest

9.1.1 · Windows

简洁而强大的 Python 自动化测试框架。

FastAPI

FastAPI

0.146.0 · Windows

高性能 Python API 框架,支持类型提示和自动接口文档。

Flask

Flask

3.1.3 · Windows

轻量灵活的 Python Web 应用框架。

Django

Django

6.1.2 · Windows

成熟的 Python Web 框架,适合构建内容站点和业务系统。

Spyder

Spyder

6.1.7 · Windows

面向科学计算与数据分析的 Python 集成开发环境。

SciPy

SciPy

1.18.1 · Windows

面向科学、工程和技术计算的 Python 算法库。