news 2026/9/15 17:54:41

Apache APISIX wolf-rbac 插件实战:基于 wolf 的 RBAC 身份认证与权限控制

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
Apache APISIX wolf-rbac 插件实战:基于 wolf 的 RBAC 身份认证与权限控制

Apache APISIX wolf-rbac 插件实战:基于 wolf 的 RBAC 身份认证与权限控制

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

导读

wolf-rbac是 Apache APISIX 中一个基于 Role-Based Access Control(RBAC,基于角色的访问控制) 为主体,结合 插件源码 与 单元测试 展开,带你完整掌握:插件的属性与接口、Consumer 与 Route 的配置方式、如何借助public-api插件暴露登录/改密/用户信息接口,以及 rbac_token 的多种携带方式与底层鉴权原理。

描述:为网关接入 wolf RBAC 鉴权

wolf-rbac插件为 APISIX 的 Route 或 Service 提供接入 wolf 权限系统的能力。它是一个认证(auth)类型插件,从源码看其优先级为2555,类型为'auth'(见 apisix/plugins/wolf-rbac.lua),意味着它会在路由匹配之后、其他业务插件执行之前完成身份与权限校验。

该插件必须与 Consumer 配合使用:插件通过 Consumer 上绑定的appid关联到具体的应用,再以该应用的身份向 wolf-server 发起权限校验。从 Consumer 术语文档 可以看到,wolf-rbacbasic-authhmac-authjwt-authkey-authldap-auth并列,是 APISIX 支持与 Consumer 配置搭配的认证插件之一。

其整体工作流程可以概括为:

  1. 用户在 wolf 系统中维护应用(appid)、用户、角色、权限、资源等数据;
  2. APISIX 在 Consumer 上绑定wolf-rbac插件并声明appid
  3. 客户端携带rbac_token请求受保护 Route;
  4. 插件解析 token,向 wolf-server 的/wolf/rbac/access_check接口查询"该用户对此 URL 的该 HTTP 方法是否有权限";
  5. 校验通过则放行并注入用户信息响应头,失败则返回 401/403 等状态码。

属性说明

wolf-rbac插件的配置属性如下表所示,这些属性与源码中的 schema 定义 一一对应:

名称类型必选项默认值描述
serverstring"http://127.0.0.1:12180"wolf-server的服务地址。
appidstring"unset"wolf-console中已经添加的应用 ID。该字段支持使用 APISIX Secret 资源,将值保存在 Secret Manager 中。
header_prefixstring"X-"自定义 HTTP 头的前缀。鉴权成功后,插件会在请求头(传给后端)与响应头(传给前端)中额外添加 3 个 header:X-UserIdX-UsernameX-Nickname

参数细节与源码印证

  • server:即 wolf-server 的访问地址,默认指向本机12180端口。从源码看,check_schema 会通过core.utils.check_https检查该地址是否为https开头,若是 HTTPS 地址则要求 APISIX 已加载相应的 SSL 证书,否则返回 schema 校验错误。
  • appid:对应 wolf 控制台中注册的应用 ID,是关联 wolf 侧权限数据的核心字段。它的默认值是字符串"unset",在单元测试 TEST 1: sanity 中可以看到,当配置为空对象时,schema 校验会填充出{"appid":"unset","header_prefix":"X-","server":"http://127.0.0.1:12180"}的完整默认配置。
  • appid支持 Secret 引用appid可写成$secret://vault/test1/wolf_rbac_unit_test/appid这样的引用形式,将敏感值托管到 Vault 等 Secret Manager 中。这一点在 测试用例 TEST 31-35 中有完整的验证:先创建 vault secret 资源,再在 Consumer 的wolf-rbac配置中使用$secret://引用,登录测试依然通过。
  • header_prefix:控制注入头的前缀。例如设置为X-时注入X-UserIdX-UsernameX-Nickname;若设置为空字符串,则注入不带前缀的UserIdUsernameNickname

插件接口

启用该插件后,它会在 APISIX 内部注册以下 3 个接口(对应源码 _M.api() 的注册表):

接口方法用途
/apisix/plugin/wolf-rbac/loginPOST用户名密码登录,换取rbac_token
/apisix/plugin/wolf-rbac/change_pwdPUT修改当前用户密码
/apisix/plugin/wolf-rbac/user_infoGET获取当前用户信息

:::note 注意

以上接口默认不对外暴露,需要通过 public-api 插件创建路由后才能从外部访问。这与public-api插件的设计一致:自定义插件注册的公共 API 端点默认隐藏,需手动配置路由启用。

:::

从源码实现看,这三个接口的 handler 都遵循同样的模式:

  • wolf_rbac_login(源码):解析请求体中的appidusernamepasswordauthType等参数,从 Consumer 配置中取出server地址,调用 wolf-server 的/wolf/rbac/login.rest接口完成认证,然后将 wolf 返回的 token 拼装成V1#appid#wolf_token格式的rbac_token返回给客户端。
  • wolf_rbac_change_pwd(源码):先从当前请求中解析rbac_token(缺 token 返回 401),再携带x-rbac-token请求头调用 wolf-server 的/wolf/rbac/change_pwd接口。
  • wolf_rbac_user_info(源码):同样先校验 token,再调用 wolf-server 的/wolf/rbac/user_info接口返回用户详情。

前提条件:安装并初始化 wolf

在使用插件之前,你必须要:

  1. 安装并启动 wolf:参考 wolf 官方提供的 Docker 快速启动方式完成部署。
  2. 初始化权限数据:在 wolf-console 控制台中添加application(应用)、admin(管理员)、regular user(普通用户)、permission(权限)、resource(资源)等数据,并将用户授权到对应应用。

注意:wolf-console 中维护的数据是鉴权的"事实来源"。APISIX 只负责把请求转发给 wolf-server 进行校验,插件本身不存储用户与权限信息。

启用插件

第一步:创建 Consumer 并绑定插件

首先创建一个 Consumer,并在其plugins中配置wolf-rbac

:::note

可以这样从 conf/config.yaml 中获取admin_key并存入环境变量(admin_key定义于deployment.admin.admin_key配置项):

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

:::

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(这里是restful),必须是已经在 wolf 控制台中存在的应用 ID,否则后续登录与鉴权都会失败。

:::

为什么appid要放在 Consumer 上?从源码的鉴权流程(rewrite 函数)可以看出,插件在收到请求后会先解析 token 中的appid,然后通过consumer.consumers_kv(plugin_name, consumer_conf, "appid")appid索引找到对应的 Consumer 配置,进而取得该应用的server地址。也就是说:一个 appid 对应一个 Consumer,token 中的 appid 决定了使用哪个 Consumer 的 wolf-server 配置。如果 token 里的 appid 找不到对应的 Consumer,插件会直接返回 401Invalid appid in rbac token(对应测试 TEST 15)。

第二步:为 Route 或 Service 添加插件

然后,将wolf-rbac插件挂载到需要保护的 Route 上。下面的示例让 Route 1 匹配所有 GET 请求并启用插件(配置项留空即可,全部使用默认值):

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 } } }'

同样地,插件也可以挂载到 Service 上,这样该 Service 下的所有 Route 都会继承鉴权配置。此外,你还可以通过 APISIX Dashboard 的 Web 界面完成上述操作。

第三步:暴露插件的三个接口(public-api)

由于/apisix/plugin/wolf-rbac/login等接口默认不对外暴露,需要创建路由并启用 public-api 插件来将它们开放出来:

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两个 API 分别配置路由(在单元测试 TEST 3: setup public API route 中,正是依次为loginuser_infochange_pwd创建了三条 public-api 路由)。

测试插件

登录并获取 rbac_token

在配置好 public-api 路由后,就可以通过网关(默认9080端口)调用登录接口了。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}'

返回示例(200 OK,响应体包含rbac_tokenuser_info):

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"}}

x-www-form-urlencoded 格式登录:

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'

:::note

  • 上述示例中,appidusernamepassword必须为 wolf 系统中真实存在的;
  • authType为认证类型:1为密码认证(默认),2为 LDAP 认证。wolf从 0.5.0 版本开始支持 LDAP 认证。

:::

rbac_token 的格式:从源码 create_rbac_token 可以看到,token 由三段以#分隔的字段组成:版本号(V1)#appid#wolf_token。其中第三段是 wolf 返回的原始 token(实际为 JWT,包含idusernameappidiatexp等声明)。解析时(parse_rbac_token)要求恰好拆成 3 段且版本号必须是V1,否则返回invalid rbac token: version

登录失败场景:单元测试 TEST 6-11 覆盖了登录接口的各种异常路径:缺少appid返回 400appid is missing、appid 不存在返回 400appid not found、用户名/密码缺失或错误、用户不存在时,网关会转发 wolf-server 返回的错误码(如ERR_USERNAME_MISSINGERR_PASSWORD_ERRORERR_USER_NOT_FOUND)并给出request to wolf-server failed!的响应。

使用受保护的 Route

现在开始测试 Route 的鉴权效果。以下场景均以示例中的rbac_token为准。

1. 缺少 token

curl http://127.0.0.1:9080/ -H"Host: www.baidu.com" -i
HTTP/1.1 401 Unauthorized ... {"message":"Missing rbac token in request"}

2. token 放到请求头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>

3. token 放到请求头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>

4. token 放到请求参数中

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>

5. token 放到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>

token 的查找优先级:以上 4 种携带方式对应源码 fetch_rbac_token 的取值顺序——依次检查 URL 参数rbac_token(注意会先做ngx.unescape_uri解码)、请求头Authorization、请求头x-rbac-tokencookie_x-rbac-token。全部取不到时返回 nil,进而触发 401。单元测试 TEST 17-20 逐一验证了这 4 种方式,且都断言了响应头中注入了X-UserId: 100X-Username: adminX-Nickname: administrator

获取用户信息

通过user_info接口,可以拿到当前 token 对应用户在 wolf 中的完整资料:

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":"" } }

更改用户密码

通过change_pwd接口修改当前用户的密码(需要携带旧密码与新密码,同时以 cookie 方式提供 token):

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"}

补充说明:从源码看,change_pwduser_info接口都要求请求中携带有效 token(get_wolf_token),否则返回 401Missing rbac token in requestinvalid rbac token: parse failed(对应测试 TEST 21-22)。同时请求体既支持 JSON 也支持 x-www-form-urlencoded(见 get_args,后者借助core.request.get_post_args解析),测试 TEST 27-28 验证了 form 方式以及超过 100 个参数场景下的可用性。

底层鉴权流程与故障处理(源码解析)

理解插件在rewrite阶段的完整处理链路,有助于在生产环境中排查问题。整个流程见 rewrite 函数:

  1. 提取上下文:获取当前请求的uri、HTTP 方法(request_method)、客户端 IP(优先取X-Real-IP,否则通过core.request.get_ip获取);
  2. 取 token:按上文优先级从参数/请求头/cookie 中提取rbac_token,缺失则返回 401Missing rbac token in request
  3. 解析 token:校验格式与版本,失败返回 401invalid rbac token: parse failed
  4. 匹配 Consumer:用 token 中的appid反查 Consumer 配置,失败返回 401Invalid appid in rbac token
  5. 调用 wolf-server 校验:向{server}/wolf/rbac/access_check?appID=...&resName=<uri>&action=<HTTP方法>&clientIP=...发起 GET 请求,并在请求头携带x-rbac-token。从 check_url_permission 可以看到,该调用带 10 秒超时,且对5xx响应最多重试 3 次(间隔 0.1 秒),以容忍 wolf-server 的瞬时故障;
  6. 注入用户信息头:校验成功后,将UserIdUsernameNicknameheader_prefix拼装,同时写入响应头(core.response.set_header,用于传给前端)和请求头(core.request.set_header,用于传给后端)。其中Nickname会经过ngx.escape_uri编码,若用户未设置昵称则回退为username
  7. 处理失败响应res.status非 200 时,直接返回 wolf-server 给出的状态码与错误信息。典型场景包括:
    • 403:用户无权限,如ERR_ACCESS_DENIED(测试 TEST 16);
    • 401:token 过期或无效,如ERR_TOKEN_INVALID(测试 TEST 30);
    • 500:wolf-server 内部错误或网络不可达,如request to wolf-server failed, status:500(测试 TEST 29)。

另外值得注意的是,wolf-server 的access_check会基于请求的 URI 与 HTTP 方法判断权限,因此同一个 Route 上不同方法的请求可能得到不同的鉴权结果——这正是 RBAC 中"资源 + 动作"模型的体现,resName即请求的uriaction即 HTTP 方法(如GETPOST)。

删除插件

当你需要禁用wolf-rbac插件时,只需通过 Admin API 将 Route(或 Service、Consumer)配置中的plugins清空,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 } } }'

注意:删除 Route 上的插件后,仅该 Route 不再鉴权。若之前在 Consumer 上也配置了wolf-rbac,可根据需要一并删除;同时由public-api暴露的loginuser_infochange_pwd三个接口路由,在不再需要时也应一并清理,避免鉴权接口继续对外开放。

小结

wolf-rbac插件将"身份认证 + 细粒度权限控制"从业务代码中剥离出来,交给网关统一处理:认证由 wolf 完成,APISIX 负责 token 解析、Consumer 匹配与权限查询,并通过注入的X-UserId/X-Username/X-Nickname头把用户身份透传给上游与前端。结合 Consumer、public-api 与 Secret 能力,它可以完整覆盖"登录换 token、携带 token 访问受保护资源、查询用户信息、修改密码"这一整套基于角色的访问控制场景。若需深入理解实现细节,可继续阅读 插件源码 与 单元测试。

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

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

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

DeepEval 怎么把 Qdrant 等向量数据库接入 RAG 评估流程?

DeepEval 怎么把 Qdrant 等向量数据库接入 RAG 评估流程&#xff1f; 【免费下载链接】deepeval The LLM Evaluation Framework 项目地址: https://gitcode.com/GitHub_Trending/de/deepeval 如果你的 RAG 系统用 Qdrant&#xff08;或 PGVector&#xff09;作为检索引擎…

作者头像 李华
网站建设 2026/9/15 17:53:51

豆包AI微信机器人接入实战:5分钟把微信机器人接上大模型

豆包AI微信机器人接入实战&#xff1a;5分钟把微信机器人接上大模型 【免费下载链接】wechat-bot &#x1f916; Multi-platform IM AI Agent for Telegram, WhatsApp, Lark, and WeChat. Connects ChatGPT / Claude / Kimi / DeepSeek / Ollama / Pi for auto-replies, commun…

作者头像 李华
网站建设 2026/9/15 17:53:30

Genesis刚体仿真确定性实战:从浮点误差到可复现控制

在研究机器人操作时&#xff0c;最糟糕的感觉是&#xff1a;模拟里同一个关节、同一个初始条件&#xff0c;把同样的策略换台机器重新跑一遍&#xff0c;结果完全不同。不是策略升级&#xff0c;是物理引擎本身在刚体仿真过程中出现了肉眼可见的漂移。那段时间我意识到&#xf…

作者头像 李华
网站建设 2026/9/15 17:53:25

STM32H7真差分ADC+以太网闭环验证实战

简介&#xff1a;本资源是面向嵌入式开发工程师与STM32进阶学习者的STM32H743多通道差分ADC采集实战项目&#xff0c;聚焦高性能MCU在工业传感、实时监测等场景下的高精度模拟数据获取与网络回传需求。项目完整实现ADC差分模式配置、多通道连续采样、DMA零拷贝传输&#xff0c;…

作者头像 李华