使用 Casbin 在 APISIX 中进行授权
简介
Apache APISIX 可以通过其内置的 authz-casbin 插件在网关处执行 Casbin 授权策略。该插件使用 Lua Casbin,并支持 ACL、RBAC 和 ABAC 等访问控制模型。
本指南在 APISIX 请求路径上设置了一个小型 RBAC 策略。您将验证允许的请求和被拒绝的请求,然后通过插件元数据更新共享策略,而无需更改路由。
Casbin 社区最初在 APISIX Issue #4674 中提出了集成方案,并且 APISIX PR #4710 添加了该插件。
本指南于 2026 年 8 月进行了刷新。示例已在 Apache APISIX 3.17.0 上进行验证。原作者仍保留署名,Yilia Lin 因 2026 年的刷新工作而被添加。
Casbin 执行的是授权,而不是认证。此示例仅为了保持测试简单,使用 user 请求头作为主体。在生产环境中,请勿信任由客户端直接提供的身份标头。应由认证层或可信代理建立身份,并在 Casbin 评估请求之前移除或覆盖不可信的值。
前提条件和初始状态
本指南从一个已经运行的临时 Apache APISIX 3.17.0 实例开始。如果您需要本地实例,请按照 APISIX Docker 部署指南 操作,并将 APISIX 镜像固定为 apache/apisix:3.17.0-debian。
该实例必须具有:
- 数据平面在
http://127.0.0.1:9080可用; - 位于
http://127.0.0.1:9180的 Admin API; - 启用了内置的
authz-casbin和mocking插件。
你还需要 curl 和 jq。将 admin_key 设置为你的
Admin API 配置的密钥:
export admin_key='<your-admin-api-key>'
在继续之前请替换占位符。确认 Admin API 可访问且插件已启用:
curl --fail-with-body \
"http://127.0.0.1:9180/apisix/admin/plugins/list" \
-H "X-API-KEY: $admin_key" | \
jq -e '(["authz-casbin", "mocking"] - .) | length == 0'
该命令应输出 true。请勿将 Admin API 发布到不受信任的网络,
或在其他环境中复用演示凭据。
定义模型和策略
该插件评估三个请求值:
sub:来自配置请求头的主体;obj:请求 URI 路径;以及act:HTTP 方法。
创建 model.conf:
[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) || keyMatch(r.sub, p.sub)) && keyMatch(r.obj, p.obj) && keyMatch(r.act, p.act)
创建 policy.csv:
p, *, /anything, GET
p, admin, *, *
g, alice, admin
此策略允许任何主体发送 GET /anything。它还分配了
alice 一个 admin 角色,该角色可以使用所有方法访问所有路径。
在插件元数据中存储共享策略
将文件加载为 JSON 字符串并将其写入 APISIX 插件元数据:
jq -n \
--rawfile model model.conf \
--rawfile policy policy.csv \
'{model: $model, policy: $policy}' | \
curl --fail-with-body \
"http://127.0.0.1:9180/apisix/admin/plugin_metadata/authz-casbin" \
-H "X-API-KEY: $admin_key" \
-H "Content-Type: application/json" \
-X PUT \
--data-binary @-
插件元数据为启用 authz-casbin 但未定义其自身路由局部模型和策略的路由
提供一套模型和策略。
在路由上启用授权
创建一个路由并告诉插件从 user 头读取主体:
curl --fail-with-body \
"http://127.0.0.1:9180/apisix/admin/routes/casbin-demo" \
-H "X-API-KEY: $admin_key" \
-H "Content-Type: application/json" \
-X PUT \
-d '{
"uri": "/*",
"plugins": {
"authz-casbin": {
"username": "user"
},
"mocking": {
"_meta": {
"priority": 1000
},
"response_status": 200,
"response_example": "{\"message\":\"authorized\"}"
}
},
"upstream": {
"type": "roundrobin",
"nodes": {
"127.0.0.1:1": 1
}
}
}'
由于该路由仅本地定义了 username 字段,因此它使用来自插件元数据的模型和策略。
如果配置了路由局部的模型和策略,则它们优先于插件元数据。
mocking 插件为允许的请求提供确定性的本地响应,因此
示例不依赖于公共上游服务。其路由局部优先级低于
authz-casbin,这使得授权决策先运行。
因此不会联系不可达的上游服务。这种优先级覆盖
和模拟响应是测试夹具,而非生产环境建议。
验证允许和拒绝决策
对公共路径的匿名请求被允许:
curl -i http://127.0.0.1:9080/anything
预期状态:
HTTP/1.1 200 OK
{"message":"authorized"}
bob 没有 admin 角色,因此不同路径被拒绝:
curl -i http://127.0.0.1:9080/anything/res -H 'user: bob'
预期结果:
HTTP/1.1 403 Forbidden
{"message":"Access Denied"}
alice 具有 admin 角色,因此相同请求被允许:
curl -i http://127.0.0.1:9080/anything/res -H 'user: alice'
预期状态:
HTTP/1.1 200 OK
{"message":"authorized"}
更新共享策略
向 policy.csv 添加针对 bob 的直接权限:
p, *, /anything, GET
p, admin, *, *
p, bob, /anything/res, GET
g, alice, admin
再次运行插件元数据命令。引用此元数据的路由使用 更新后的策略而无需更改其路由配置。重复请求:
curl -i http://127.0.0.1:9080/anything/res -H 'user: bob'
现在的预期结果是:
HTTP/1.1 200 OK
{"message":"authorized"}
选择配置范围
当多个路由应共享一套模型和策略时,使用插件元数据。当路由需要独立的授权
结构时,使用路由局部的模型和策略。有关完整的配置架构和基于文件的替代方案,请参阅
APISIX authz-casbin 插件参考。
清理
移除测试路由:
curl --fail-with-body \
"http://127.0.0.1:9180/apisix/admin/routes/casbin-demo" \
-H "X-API-KEY: $admin_key" \
-X DELETE
移除共享插件元数据:
curl --fail-with-body \
"http://127.0.0.1:9180/apisix/admin/plugin_metadata/authz-casbin" \
-H "X-API-KEY: $admin_key" \
-X DELETE

Comments are powered by giscus and GitHub Discussions. They load from giscus.app and GitHub only after you click the button below.