news 2026/9/15 19:15:59

使用 wolf-rbac 插件为 Apache APISIX 接入基于 wolf 的角色访问控制(RBAC)

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
使用 wolf-rbac 插件为 Apache APISIX 接入基于 wolf 的角色访问控制(RBAC)

使用 wolf-rbac 插件为 Apache APISIX 接入基于 wolf 的角色访问控制(RBAC)

【免费下载链接】apisixThe Cloud-Native API Gateway项目地址: https://gitcode.com/GitHub_Trending/ap/apisix

wolf-rbac是 Apache APISIX 内置的认证类插件,它将开源权限系统 wolf 的基于角色的访问控制(RBAC)能力以网关插件的形式接入 Route 与 Service,并与 Consumer 对象深度绑定,实现"先登录换令牌、再按资源+动作鉴权"的完整流程。读完本文,你将掌握 wolf-rbac 的全部配置属性、内置 API 端点、与 public-api 配合的暴露方式、四种令牌传递方式,以及从源码层面理解其鉴权调用链,能够独立完成从部署 wolf 到网关鉴权上线的全链路接入。

一、插件简介:把 RBAC 决策交给 wolf,把执行放在网关

wolf-rbac插件将 role-based access control(基于角色的访问控制) 系统 wolf 与 APISIX 打通:wolf 负责用户的认证(登录、改密)与授权(权限、资源、角色管理),APISIX 网关负责在请求进入时校验令牌、向 wolf 发起访问控制查询,并把用户身份透传给后端。

从源码结构看,插件在 apisix/plugins/wolf-rbac.lua 中定义为:

local _M = { version = 0.1, priority = 2555, type = 'auth', name = plugin_name, schema = schema, }
  • type = 'auth':属于认证类插件,可与 Consumer 绑定使用;
  • priority = 2555:优先级较高,确保在路由匹配后、其他业务插件之前执行鉴权逻辑;
  • 鉴权核心逻辑在rewrite阶段完成,即请求在进入上游之前就被拦截校验。

该插件可与 Consumer 配合使用:每个 Consumer 上配置一个appid,网关通过令牌中的appid定位对应的 Consumer 与 wolf 服务地址,从而支持多个应用(多租户)共用一套 APISIX 网关、各自对接不同的 wolf 配置。

二、配置属性详解

wolf-rbac的配置属性如下:

名称类型必填默认值描述
serverstring"http://127.0.0.1:12180"wolf 服务的地址
appidstring"unset"在 wolf 控制台中添加的应用 ID(App id),该字段支持通过 APISIX Secret 资源保存到密钥管理器中
header_prefixstring"X-"自定义 HTTP 头前缀。认证成功后,会向后端请求头与前端响应头中各添加三个头:X-UserIdX-UsernameX-Nickname

属性细节与源码印证

以上默认值可以直接在源码的 schema 定义中看到(apisix/plugins/wolf-rbac.lua):

local schema = { type = "object", properties = { appid = { type = "string", default = "unset" }, server = { type = "string", default = "http://127.0.0.1:12180" }, header_prefix = { type = "string", default = "X-" }, } }

在测试用例 t/plugin/wolf-rbac.t 的 TEST 1 中,不传任何配置时check_schema会得到默认值{"appid":"unset","header_prefix":"X-","server":"http:\/\/127\.0\.0\.1:12180"};TEST 2 则验证了类型校验——appid传入数字会报错property "appid" validation failed: wrong type: expected string, got number

需要注意:server的值在运行时决定与 wolf 通信的目标地址,因此同一个 APISIX 集群可以为不同 Consumer 配置不同的 wolf 服务端;而appid必须是在 wolf 控制台中真实存在并已完成资源授权的应用 ID,否则登录与鉴权都会失败。

header_prefix的可配置性意味着在多应用共用网关时,可以避免不同应用的认证头互相冲突(例如配置为App-后,透传头变为App-UserId等)。

三、插件内置 API 端点

启用该插件后,会注册以下三个内部 API 端点(源码见 apisix/plugins/wolf-rbac.lua 的_M.api()):

端点HTTP 方法功能
/apisix/plugin/wolf-rbac/loginPOST用户登录,返回rbac_token与用户信息
/apisix/plugin/wolf-rbac/change_pwdPUT修改用户密码
/apisix/plugin/wolf-rbac/user_infoGET获取当前用户信息

:::note 与 jwt-auth 等插件一致,这些端点默认不对外暴露,需要通过 public-api 插件配合一条 Route 将其公开。 :::

public-api插件(源码见 apisix/plugins/public-api.lua)的作用是把插件内部注册的 API 通过通用 HTTP 路由暴露出去:在 Route 上启用public-api后,其access阶段会调用router.api.match(ctx)完成内部 API 路由匹配,从而把请求转发给 wolf-rbac 的内部 handler。

四、前置条件:先准备好 wolf 服务端

使用本插件前,必须先在环境中安装并启动 wolf,然后通过 wolf-console 完成以下配置:

  1. 安装并启动 wolf(可采用其官方仓库提供的 Docker 快速启动方式);
  2. 在 wolf-console 中依次添加:application(应用)、admin(管理员)、normal user(普通用户)、permission(权限)、resource(资源);
  3. 为上述用户完成授权(user authorize),使该用户对相关资源拥有对应操作的权限。

这些配置直接决定了后续登录、访问控制查询的结果:登录依赖 wolf 中存在的用户与密码,鉴权依赖 wolf 中"资源 + 动作 + 用户角色"的授权关系。

五、启用插件

wolf-rbac的配置必须挂在 Consumer 上(在 Route 上仅写"wolf-rbac": {}空配置即可),这样网关才能通过令牌中的appid找到对应的 wolf 服务地址与 Consumer 上下文。

5.1 获取 admin_key

Admin API 默认开启了认证(对应 conf/config.yaml.example 中的admin_key_required: trueadmin_key配置)。可以从config.yaml中取出 admin key 并保存为环境变量:

admin_key=$(yq '.deployment.admin.admin_key[0].key' conf/config.yaml | sed 's/"//g')

5.2 在 Consumer 上配置插件

curl http://127.0.0.1:9180/apisix/admin/consumers -H "X-API-KEY: $admin_key" -X PUT -d ' { "username":"wolf_rbac", "plugins":{ "wolf-rbac":{ "server":"http://127.0.0.1:12180", "appid":"restful" } }, "desc":"wolf-rbac" }'

:::note 配置中的appid必须已经在 wolf 中存在,否则后续登录/鉴权会失败。 :::

从源码实现看,网关在鉴权时通过consumer.plugin(plugin_name)获取全局的 wolf-rbac Consumer 配置,再用consumer.consumers_kv(plugin_name, consumer_conf, "appid")appid为键建立索引(见 apisix/plugins/wolf-rbac.lua),因此一个 Consumer 对应一个 appid、一个 wolf 服务地址是设计上的基本单元。

5.3 将插件绑定到 Route 或 Service

curl http://127.0.0.1:9180/apisix/admin/routes/1 -H "X-API-KEY: $admin_key" -X PUT -d ' { "methods": ["GET"], "uri": "/*", "plugins": { "wolf-rbac": {} }, "upstream": { "type": "roundrobin", "nodes": { "www.baidu.com:80": 1 } } }'

也可以使用 APISIX Dashboard 通过 Web 界面完成上述操作(添加 Consumer、启用 wolf-rbac 插件)。

六、使用示例:从登录到访问受保护资源

6.1 用 public-api 暴露登录端点

wolf-rbac 的内部 API 默认不对外,需要先创建一条启用public-api插件的 Route:

curl http://127.0.0.1:9180/apisix/admin/routes/wal -H "X-API-KEY: $admin_key" -X PUT -d ' { "uri": "/apisix/plugin/wolf-rbac/login", "plugins": { "public-api": {} } }'

change_pwduser_info两个端点同样需要各自创建一条 public-api Route 才能对外访问。

6.2 登录并获取 rbac_token

使用 JSON 请求体登录:

curl http://127.0.0.1:9080/apisix/plugin/wolf-rbac/login -i \ -H "Content-Type: application/json" \ -d '{"appid": "restful", "username":"test", "password":"user-password", "authType":1}'

响应示例:

HTTP/1.1 200 OK Date: Wed, 24 Jul 2019 10:33:31 GMT Content-Type: text/plain Transfer-Encoding: chunked Connection: keep-alive Server: APISIX web server {"rbac_token":"V1#restful#eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpZCI6NzQ5LCJ1c2VybmFtZSI6InRlc3QiLCJtYW5hZ2VyIjoiIiwiYXBwaWQiOiJyZXN0ZnVsIiwiaWF0IjoxNTc5NDQ5ODQxLCJleHAiOjE1ODAwNTQ2NDF9.n2-830zbhrEh6OAxn4K_yYtg5pqfmjpZAjoQXgtcuts","user_info":{"nickname":"test","username":"test","id":"749"}}

:::note 请求中的appidusernamepassword必须在 wolf 系统中预先配置;authType为认证类型——1 表示密码认证(默认),2 表示 LDAP 认证(v0.5.0+)。 :::

也可以使用x-www-form-urlencoded表单方式提交(源码get_args会先判断Content-Type是否为application/json,否则走core.request.get_post_args解析表单,见 apisix/plugins/wolf-rbac.lua):

curl http://127.0.0.1:9080/apisix/plugin/wolf-rbac/login -i \ -H "Content-Type: application/x-www-form-urlencoded" \ -d 'appid=restful&username=test&password=user-password'

登录成功后,网关会把 wolf 返回的 token 包装成统一格式的rbac_token。从源码看其格式为V1#appid#wolf_token(见create_rbac_token,apisix/plugins/wolf-rbac.lua),wolf_token本体是 wolf 签发的 JWT。

6.3 携带令牌访问受保护路由

wolf-rbac支持四种令牌传递方式,网关按固定顺序从请求中提取令牌(源码fetch_rbac_token,见 apisix/plugins/wolf-rbac.lua):

  1. URL 查询参数rbac_tokenctx.var.arg_rbac_token,会自动进行 URL 解码);
  2. Authorization请求头;
  3. x-rbac-token请求头;
  4. Cookiex-rbac-token

下面逐一验证:

  • 不带令牌:返回401 Unauthorized
curl http://127.0.0.1:9080/ -H"Host: www.baidu.com" -i
HTTP/1.1 401 Unauthorized ... {"message":"Missing rbac token in request"}
  • 放在Authorization头中
curl http://127.0.0.1:9080/ -H"Host: www.baidu.com" \ -H 'Authorization: V1#restful#eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpZCI6NzQ5LCJ1c2VybmFtZSI6InRlc3QiLCJtYW5hZ2VyIjoiIiwiYXBwaWQiOiJyZXN0ZnVsIiwiaWF0IjoxNTc5NDQ5ODQxLCJleHAiOjE1ODAwNTQ2NDF9.n2-830zbhrEh6OAxn4K_yYtg5pqfmjpZAjoQXgtcuts' -i
HTTP/1.1 200 OK <!DOCTYPE html>
  • 放在x-rbac-token头中
curl http://127.0.0.1:9080/ -H"Host: www.baidu.com" \ -H 'x-rbac-token: V1#restful#eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpZCI6NzQ5LCJ1c2VybmFtZSI6InRlc3QiLCJtYW5hZ2VyIjoiIiwiYXBwaWQiOiJyZXN0ZnVsIiwiaWF0IjoxNTc5NDQ5ODQxLCJleHAiOjE1ODAwNTQ2NDF9.n2-830zbhrEh6OAxn4K_yYtg5pqfmjpZAjoQXgtcuts' -i
HTTP/1.1 200 OK <!DOCTYPE html>
  • 放在 URL 查询参数中
curl 'http://127.0.0.1:9080?rbac_token=V1%23restful%23eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpZCI6NzQ5LCJ1c2VybmFtZSI6InRlc3QiLCJtYW5hZ2VyIjoiIiwiYXBwaWQiOiJyZXN0ZnVsIiwiaWF0IjoxNTc5NDQ5ODQxLCJleHAiOjE1ODAwNTQ2NDF9.n2-830zbhrEh6OAxn4K_yYtg5pqfmjpZAjoQXgtcuts' -H"Host: www.baidu.com" -i
HTTP/1.1 200 OK <!DOCTYPE html>
  • 放在 Cookie 中
curl http://127.0.0.1:9080 -H"Host: www.baidu.com" \ --cookie x-rbac-token=V1#restful#eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpZCI6NzQ5LCJ1c2VybmFtZSI6InRlc3QiLCJtYW5hZ2VyIjoiIiwiYXBwaWQiOiJyZXN0ZnVsIiwiaWF0IjoxNTc5NDQ5ODQxLCJleHAiOjE1ODAwNTQ2NDF9.n2-830zbhrEh6OAxn4K_yYtg5pqfmjpZAjoQXgtcuts -i
HTTP/1.1 200 OK <!DOCTYPE html>

上述四种方式在测试用例 t/plugin/wolf-rbac.t 的 TEST 17~20 中均有覆盖,且都断言了响应头中透传的X-UserId: 100X-Username: adminX-Nickname: administrator

6.4 获取用户信息

curl http://127.0.0.1:9080/apisix/plugin/wolf-rbac/user_info \ --cookie x-rbac-token=V1#restful#eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpZCI6NzQ5LCJ1c2VybmFtZSI6InRlc3QiLCJtYW5hZ2VyIjoiIiwiYXBwaWQiOiJyZXN0ZnVsIiwiaWF0IjoxNTc5NDQ5ODQxLCJleHAiOjE1ODAwNTQ2NDF9.n2-830zbhrEh6OAxn4K_yYtg5pqfmjpZAjoQXgtcuts -i
HTTP/1.1 200 OK { "user_info":{ "nickname":"test", "lastLogin":1582816780, "id":749, "username":"test", "appIDs":["restful"], "manager":"none", "permissions":{"USER_LIST":true}, "profile":null, "roles":{}, "createTime":1578820506, "email":"" } }

6.5 修改用户密码

curl http://127.0.0.1:9080/apisix/plugin/wolf-rbac/change_pwd \ -H "Content-Type: application/json" \ --cookie x-rbac-token=V1#restful#eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpZCI6NzQ5LCJ1c2VybmFtZSI6InRlc3QiLCJtYW5hZ2VyIjoiIiwiYXBwaWQiOiJyZXN0ZnVsIiwiaWF0IjoxNTc5NDQ5ODQxLCJleHAiOjE1ODAwNTQ2NDF9.n2-830zbhrEh6OAxn4K_yYtg5pqfmjpZAjoQXgtcuts -i \ -X PUT -d '{"oldPassword": "old password", "newPassword": "new password"}'
HTTP/1.1 200 OK {"message":"success to change password"}

七、鉴权流程:源码级调用链解读

rewrite阶段,插件对每个进入受保护路由的请求执行如下步骤(核心逻辑见 apisix/plugins/wolf-rbac.lua 的_M.rewrite):

  1. 提取令牌:按"查询参数 → Authorization 头 → x-rbac-token 头 → Cookie"的顺序调用fetch_rbac_token;取不到令牌直接返回401 {"message":"Missing rbac token in request"}(对应测试 TEST 13)。
  2. 解析令牌parse_rbac_token#分割为三段,校验版本号必须是V1、且段数为 3;格式非法返回401 {"message":"invalid rbac token: parse failed"}(对应测试 TEST 14)。
  3. 定位 Consumer:以令牌中的appid为键查找 Consumer;未找到返回401 {"message":"Invalid appid in rbac token"}(对应测试 TEST 15,日志会输出consumer [invalid-appid] not found)。
  4. 向 wolf 发起访问控制查询:调用check_url_permission,请求{server}/wolf/rbac/access_check,携带x-rbac-token(wolf 原始 JWT)、appIDresName(当前请求 URI)、action(当前 HTTP 方法)、clientIP等参数;该请求设置了 10 秒超时,并在遇到 5xx 状态码时最多重试 3 次、每次间隔 100ms(见 apisix/plugins/wolf-rbac.lua)。
  5. 处理鉴权结果:wolf 返回非 200 时,按原因返回对应错误(如ERR_ACCESS_DENIED对应 403、ERR_TOKEN_INVALID对应 401、wolf 服务 5xx 对应 500);校验通过后调用consumer.attach_consumer将 Consumer 上下文绑定到请求,供后续插件使用。
  6. 身份透传:鉴权通过后,把userInfo中的idusernamenickname分别以{header_prefix}UserId{header_prefix}Username{header_prefix}Nickname写入后端请求头前端响应头nickname会做ngx.escape_uri编码),默认即X-UserIdX-UsernameX-Nickname

测试用例 TEST 29、TEST 30 还覆盖了异常路径:wolf 返回 500 时网关返回{"message":"request to wolf-server failed, status:500"},令牌过期时返回ERR_TOKEN_INVALID。TEST 36~37 则验证了 wolf-rbac 与 Consumer 上其他插件(如 echo)的合并执行,证明认证通过后 Consumer 级插件配置会正常生效。

八、进阶:使用 Secret 管理 appid

appid字段支持 APISIX Secret 引用,避免敏感信息以明文出现在 Consumer 配置中。例如先把密钥存入 HashiCorp Vault:

VAULT_TOKEN='root' VAULT_ADDR='http://0.0.0.0:8200' vault kv put kv/apisix/wolf_rbac_unit_test appid=wolf-rbac-app

再在 Consumer 配置中通过$secret://引用:

curl http://127.0.0.1:9180/apisix/admin/consumers -H "X-API-KEY: $admin_key" -X PUT -d ' { "username": "wolf_rbac_unit_test", "plugins": { "wolf-rbac": { "appid": "$secret://vault/test1/wolf_rbac_unit_test/appid", "server": "http://127.0.0.1:1982" } } }'

其中test1是预先通过 Admin API(/apisix/admin/secrets/vault/test1)创建的 Vault 资源 ID。测试用例 t/plugin/wolf-rbac.t 的 TEST 31~35 完整覆盖了"Vault 存密钥 → Secret 引用 → 登录成功"的链路,并且也验证了 Vault token 本身可以用$ENV://VAULT_TOKEN环境变量引用。

九、删除插件

要移除wolf-rbac插件,只需把对应配置从 Route/Service/Consumer 的 JSON 配置中删除。APISIX 会自动热加载新配置,无需重启即可生效:

curl http://127.0.0.1:9180/apisix/admin/routes/1 -H "X-API-KEY: $admin_key" -X PUT -d ' { "methods": ["GET"], "uri": "/*", "plugins": { }, "upstream": { "type": "roundrobin", "nodes": { "www.baidu.com:80": 1 } } }'

十、小结与实践建议

wolf-rbac为 APISIX 提供了与 wolf 深度集成的 RBAC 能力,其核心设计可以概括为三点:

  • 配置集中serverappid定义在 Consumer 上,一个 Consumer 对应一个 wolf 应用,天然支持多应用多租户;
  • 执行前置:鉴权在rewrite阶段完成,未认证请求在进入上游前即被拦截,令牌支持请求头、Cookie、查询参数多种携带方式,适配 Web 与移动端场景;
  • 身份可透传:认证通过后自动向后端与前端注入X-UserId/X-Username/X-Nickname三个头,后端无需再解析令牌即可获得用户身份。

实践中建议将appid等敏感字段通过 APISIX Secret 管理;登录、改密、用户信息三个端点务必通过 public-api 明确暴露(必要时可再叠加其他访问限制插件),避免内部 API 被随意调用。完整的端到端行为可以参照测试用例 t/plugin/wolf-rbac.t 验证,插件实现源码位于 apisix/plugins/wolf-rbac.lua。

【免费下载链接】apisixThe Cloud-Native API Gateway项目地址: https://gitcode.com/GitHub_Trending/ap/apisix

创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/9/15 19:15:26

Pytorch实现DenseNet:密集连接、特征复用与CIFAR-10训练实战

简介&#xff1a;基于Pytorch实现DenseNet的完整项目源码&#xff0c;面向希望系统掌握经典卷积神经网络结构与Pytorch工程实现的开发者、研究人员及深度学习初学者。项目围绕DenseNet的核心机制展开&#xff0c;覆盖稠密块、过渡层、增长率与瓶颈层等关键设计&#xff0c;并配…

作者头像 李华
网站建设 2026/9/15 19:14:29

FreeCAD参数化建模实操:从一张草图到成品实体的完整流程

FreeCAD参数化建模实操&#xff1a;从一张草图到成品实体的完整流程 【免费下载链接】FreeCAD Official source code of FreeCAD, a free and opensource multiplatform 3D parametric modeler. 项目地址: https://gitcode.com/GitHub_Trending/fr/FreeCAD 想零成本入门…

作者头像 李华
网站建设 2026/9/15 19:11:00

Flutter邮件验证库在OpenHarmony平台的适配实践

1. 项目背景与需求分析在跨平台应用开发领域&#xff0c;Flutter因其高效的渲染性能和统一的代码库管理&#xff0c;已成为移动端开发的主流选择之一。而OpenHarmony作为新兴的分布式操作系统&#xff0c;其生态建设正处于快速发展阶段。将Flutter生态中的成熟组件移植到OpenHa…

作者头像 李华