使用 wolf-rbac 插件为 Apache APISIX 接入基于 wolf 的角色访问控制(RBAC) 使用 wolf-rbac 插件为 Apache APISIX 接入基于 wolf 的角色访问控制RBAC【免费下载链接】apisixThe Cloud-Native API Gateway项目地址: https://gitcode.com/GitHub_Trending/ap/apisixwolf-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:12180wolf 服务的地址appidstring否unset在 wolf 控制台中添加的应用 IDApp id该字段支持通过 APISIX Secret 资源保存到密钥管理器中header_prefixstring否X-自定义 HTTP 头前缀。认证成功后会向后端请求头与前端响应头中各添加三个头X-UserId、X-Username、X-Nickname属性细节与源码印证以上默认值可以直接在源码的 schema 定义中看到apisix/plugins/wolf-rbac.lualocal 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 完成以下配置安装并启动 wolf可采用其官方仓库提供的 Docker 快速启动方式在 wolf-console 中依次添加application应用、admin管理员、normal user普通用户、permission权限、resource资源为上述用户完成授权user authorize使该用户对相关资源拥有对应操作的权限。这些配置直接决定了后续登录、访问控制查询的结果登录依赖 wolf 中存在的用户与密码鉴权依赖 wolf 中资源 动作 用户角色的授权关系。五、启用插件wolf-rbac的配置必须挂在 Consumer 上在 Route 上仅写wolf-rbac: {}空配置即可这样网关才能通过令牌中的appid找到对应的 wolf 服务地址与 Consumer 上下文。5.1 获取 admin_keyAdmin API 默认开启了认证对应 conf/config.yaml.example 中的admin_key_required: true与admin_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 或 Servicecurl 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插件的 Routecurl 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_pwd与user_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 请求中的appid、username、password必须在 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.luacurl http://127.0.0.1:9080/apisix/plugin/wolf-rbac/login -i \ -H Content-Type: application/x-www-form-urlencoded \ -d appidrestfulusernametestpassworduser-password登录成功后网关会把 wolf 返回的 token 包装成统一格式的rbac_token。从源码看其格式为V1#appid#wolf_token见create_rbac_tokenapisix/plugins/wolf-rbac.luawolf_token本体是 wolf 签发的 JWT。6.3 携带令牌访问受保护路由wolf-rbac支持四种令牌传递方式网关按固定顺序从请求中提取令牌源码fetch_rbac_token见 apisix/plugins/wolf-rbac.luaURL 查询参数rbac_tokenctx.var.arg_rbac_token会自动进行 URL 解码Authorization请求头x-rbac-token请求头Cookiex-rbac-token。下面逐一验证不带令牌返回401 Unauthorizedcurl http://127.0.0.1:9080/ -HHost: www.baidu.com -iHTTP/1.1 401 Unauthorized ... {message:Missing rbac token in request}放在Authorization头中curl http://127.0.0.1:9080/ -HHost: www.baidu.com \ -H Authorization: V1#restful#eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpZCI6NzQ5LCJ1c2VybmFtZSI6InRlc3QiLCJtYW5hZ2VyIjoiIiwiYXBwaWQiOiJyZXN0ZnVsIiwiaWF0IjoxNTc5NDQ5ODQxLCJleHAiOjE1ODAwNTQ2NDF9.n2-830zbhrEh6OAxn4K_yYtg5pqfmjpZAjoQXgtcuts -iHTTP/1.1 200 OK !DOCTYPE html放在x-rbac-token头中curl http://127.0.0.1:9080/ -HHost: www.baidu.com \ -H x-rbac-token: V1#restful#eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpZCI6NzQ5LCJ1c2VybmFtZSI6InRlc3QiLCJtYW5hZ2VyIjoiIiwiYXBwaWQiOiJyZXN0ZnVsIiwiaWF0IjoxNTc5NDQ5ODQxLCJleHAiOjE1ODAwNTQ2NDF9.n2-830zbhrEh6OAxn4K_yYtg5pqfmjpZAjoQXgtcuts -iHTTP/1.1 200 OK !DOCTYPE html放在 URL 查询参数中curl http://127.0.0.1:9080?rbac_tokenV1%23restful%23eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpZCI6NzQ5LCJ1c2VybmFtZSI6InRlc3QiLCJtYW5hZ2VyIjoiIiwiYXBwaWQiOiJyZXN0ZnVsIiwiaWF0IjoxNTc5NDQ5ODQxLCJleHAiOjE1ODAwNTQ2NDF9.n2-830zbhrEh6OAxn4K_yYtg5pqfmjpZAjoQXgtcuts -HHost: www.baidu.com -iHTTP/1.1 200 OK !DOCTYPE html放在 Cookie 中curl http://127.0.0.1:9080 -HHost: www.baidu.com \ --cookie x-rbac-tokenV1#restful#eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpZCI6NzQ5LCJ1c2VybmFtZSI6InRlc3QiLCJtYW5hZ2VyIjoiIiwiYXBwaWQiOiJyZXN0ZnVsIiwiaWF0IjoxNTc5NDQ5ODQxLCJleHAiOjE1ODAwNTQ2NDF9.n2-830zbhrEh6OAxn4K_yYtg5pqfmjpZAjoQXgtcuts -iHTTP/1.1 200 OK !DOCTYPE html上述四种方式在测试用例 t/plugin/wolf-rbac.t 的 TEST 17~20 中均有覆盖且都断言了响应头中透传的X-UserId: 100、X-Username: admin、X-Nickname: administrator。6.4 获取用户信息curl http://127.0.0.1:9080/apisix/plugin/wolf-rbac/user_info \ --cookie x-rbac-tokenV1#restful#eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpZCI6NzQ5LCJ1c2VybmFtZSI6InRlc3QiLCJtYW5hZ2VyIjoiIiwiYXBwaWQiOiJyZXN0ZnVsIiwiaWF0IjoxNTc5NDQ5ODQxLCJleHAiOjE1ODAwNTQ2NDF9.n2-830zbhrEh6OAxn4K_yYtg5pqfmjpZAjoQXgtcuts -iHTTP/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-tokenV1#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提取令牌按查询参数 → Authorization 头 → x-rbac-token 头 → Cookie的顺序调用fetch_rbac_token取不到令牌直接返回401 {message:Missing rbac token in request}对应测试 TEST 13。解析令牌parse_rbac_token按#分割为三段校验版本号必须是V1、且段数为 3格式非法返回401 {message:invalid rbac token: parse failed}对应测试 TEST 14。定位 Consumer以令牌中的appid为键查找 Consumer未找到返回401 {message:Invalid appid in rbac token}对应测试 TEST 15日志会输出consumer [invalid-appid] not found。向 wolf 发起访问控制查询调用check_url_permission请求{server}/wolf/rbac/access_check携带x-rbac-tokenwolf 原始 JWT、appID、resName当前请求 URI、action当前 HTTP 方法、clientIP等参数该请求设置了 10 秒超时并在遇到 5xx 状态码时最多重试 3 次、每次间隔 100ms见 apisix/plugins/wolf-rbac.lua。处理鉴权结果wolf 返回非 200 时按原因返回对应错误如ERR_ACCESS_DENIED对应 403、ERR_TOKEN_INVALID对应 401、wolf 服务 5xx 对应 500校验通过后调用consumer.attach_consumer将 Consumer 上下文绑定到请求供后续插件使用。身份透传鉴权通过后把userInfo中的id、username、nickname分别以{header_prefix}UserId、{header_prefix}Username、{header_prefix}Nickname写入后端请求头与前端响应头nickname会做ngx.escape_uri编码默认即X-UserId、X-Username、X-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 管理 appidappid字段支持 APISIX Secret 引用避免敏感信息以明文出现在 Consumer 配置中。例如先把密钥存入 HashiCorp VaultVAULT_TOKENroot VAULT_ADDRhttp://0.0.0.0:8200 vault kv put kv/apisix/wolf_rbac_unit_test appidwolf-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 能力其核心设计可以概括为三点配置集中server与appid定义在 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),仅供参考