a6-plugin-wolf-rbac
概览
wolf-rbac 插件通过集成 Wolf RBAC 服务器 提供基于角色的访问控制(RBAC)。它支持集中认证,以及跨多个应用的基于 URL 和方法的细粒度权限检查,无需修改后端服务。
优先级: 2555(身份验证插件,在 rewrite 阶段运行)。
适用场景
- 跨多个 HTTP 应用的集中式 RBAC
- URL + HTTP 方法级别的权限控制
- 面向微服务的统一用户管理
- 需要登录、用户信息和修改密码 API 端点
前提条件
- Wolf RBAC 服务器 已运行(默认
http://127.0.0.1:12180) - 在 Wolf 控制台中配置:Application → Users → Roles → Permissions → Resources
- 通过 Docker 安装 Wolf:
https://github.com/iGeeky/wolf/blob/master/quick-start-with-docker/README.md
插件配置参考(消费者)
| 字段 | 类型 | 是否必填 | 默认值 | 说明 |
|---|---|---|---|---|
server | string | 否 | http://127.0.0.1:12180 | Wolf RBAC 服务器 URL |
appid | string | 否 | unset | 在 Wolf 控制台中注册的应用 ID |
header_prefix | string | 否 | X- | 注入请求头的前缀(UserId、Username、Nickname) |
注意: 请在消费者上配置该插件,而不是在路由上配置。路由配置应为空对象 {}。
Token 格式
V1#<appid>#<wolf_jwt_token>
示例:V1#restful#eyJhbGciOiJIUzI1NiIs...
Token 提取优先级
- 查询参数:
?rbac_token=V1%23app%23token(URL 编码) - Authorization 请求头:
Authorization: V1#app#token - 自定义请求头:
x-rbac-token: V1#app#token - Cookie:
x-rbac-token=V1#app#token
API 端点
该插件会注册三个端点(必须通过 public-api 插件暴露):
POST /apisix/plugin/wolf-rbac/login
认证并获取 rbac_token。
请求:
{
"appid": "restful",
"username": "test",
"password": "user-password",
"authType": 1
}
authType:1= 密码(默认),2= LDAP(Wolf v0.5.0+)
响应(200):
{
"rbac_token": "V1#restful#eyJhbGci...",
"user_info": {"id": "749", "username": "test", "nickname": "test"}
}
GET /apisix/plugin/wolf-rbac/user_info
获取已认证用户详情。需要有效的 rbac_token。
响应(200):
{
"user_info": {
"id": 749,
"username": "test",
"nickname": "test",
"permissions": {"USER_LIST": true},
"roles": {}
}
}
PUT /apisix/plugin/wolf-rbac/change_pwd
修改密码。需要有效的 rbac_token。
请求:
{"oldPassword": "old", "newPassword": "new"}
授权流程
1. Client sends request with rbac_token
2. APISIX parses token → extracts appid + wolf_token
3. Matches appid to Consumer configuration
4. Calls Wolf server: GET /wolf/rbac/access_check
- appID, resName (URL), action (HTTP method), clientIP
5. Wolf checks user roles/permissions for the resource
6. Success → inject X-UserId, X-Username, X-Nickname headers
7. Failure → return 401 (invalid token) or 403 (no permission)
重试行为: 对 Wolf 服务器的 5xx 错误最多重试 3 次,每次间隔 100ms。
分步设置
1. 创建消费者
a6 consumer create -f - <<'EOF'
{
"username": "wolf_rbac",
"plugins": {
"wolf-rbac": {
"server": "http://127.0.0.1:12180",
"appid": "restful"
}
}
}
EOF
2. 创建受保护路由
a6 route create -f - <<'EOF'
{
"id": "protected-api",
"uri": "/api/*",
"plugins": {
"wolf-rbac": {}
},
"upstream": {
"type": "roundrobin",
"nodes": {"backend:8080": 1}
}
}
EOF
3. 暴露登录端点
a6 route create -f - <<'EOF'
{
"id": "wolf-login",
"uri": "/apisix/plugin/wolf-rbac/login",
"plugins": {
"public-api": {}
}
}
EOF
4. 暴露用户信息端点
a6 route create -f - <<'EOF'
{
"id": "wolf-userinfo",
"uri": "/apisix/plugin/wolf-rbac/user_info",
"plugins": {
"public-api": {}
}
}
EOF
5. 暴露修改密码端点
a6 route create -f - <<'EOF'
{
"id": "wolf-changepwd",
"uri": "/apisix/plugin/wolf-rbac/change_pwd",
"plugins": {
"public-api": {}
}
}
EOF
6. 测试登录
curl -X POST http://127.0.0.1:9080/apisix/plugin/wolf-rbac/login \
-H "Content-Type: application/json" \
-d '{"appid":"restful","username":"test","password":"user-password"}'
7. 访问受保护资源
curl http://127.0.0.1:9080/api/users \
-H "Authorization: V1#restful#<token_from_step_6>"
多应用设置
# App 1 consumer
a6 consumer create -f - <<'EOF'
{
"username": "wolf_app1",
"plugins": {
"wolf-rbac": {
"server": "http://127.0.0.1:12180",
"appid": "app1"
}
}
}
EOF
# App 2 consumer
a6 consumer create -f - <<'EOF'
{
"username": "wolf_app2",
"plugins": {
"wolf-rbac": {
"server": "http://127.0.0.1:12180",
"appid": "app2"
}
}
}
EOF
Token 中的每个 appid 都决定使用哪个消费者(以及哪个 Wolf 应用)
进行权限检查。
自定义请求头前缀
a6 consumer create -f - <<'EOF'
{
"username": "wolf_custom",
"plugins": {
"wolf-rbac": {
"server": "http://127.0.0.1:12180",
"appid": "myapp",
"header_prefix": "Wolf-"
}
}
}
EOF
注入后的请求头为:Wolf-UserId、Wolf-Username、Wolf-Nickname。
配置同步示例
version: "1"
consumers:
- username: wolf_rbac
plugins:
wolf-rbac:
server: "http://127.0.0.1:12180"
appid: restful
routes:
- id: protected-api
uri: /api/*
plugins:
wolf-rbac: {}
upstream_id: api-backend
- id: wolf-login
uri: /apisix/plugin/wolf-rbac/login
plugins:
public-api: {}
- id: wolf-userinfo
uri: /apisix/plugin/wolf-rbac/user_info
plugins:
public-api: {}
- id: wolf-changepwd
uri: /apisix/plugin/wolf-rbac/change_pwd
plugins:
public-api: {}
注入的请求头
认证成功后,这些请求头会添加到请求 (上游)和响应(客户端)中:
| 请求头 | 示例 | 说明 |
|---|---|---|
{prefix}UserId | X-UserId: 749 | Wolf 用户 ID |
{prefix}Username | X-Username: admin | Wolf 用户名 |
{prefix}Nickname | X-Nickname: administrator | URL 编码的昵称 |
错误响应
| 状态码 | 消息 | 原因 |
|---|---|---|
| 401 | Missing rbac token in request | 任一受支持位置均未提供 Token |
| 401 | invalid rbac token: parse failed | Token 格式不是 V1#appid#jwt |
| 401 | Invalid appid in rbac token | 没有 appid 匹配的消费者 |
| 401 | ERR_TOKEN_INVALID | JWT 已过期或签名无效 |
| 403 | ERR_ACCESS_DENIED | 用户缺少 URL + 方法权限 |
| 500 | request to wolf-server failed | Wolf 服务器不可达或发生错误 |
安全建议
- 生产环境中为 Wolf 服务器 URL 使用 HTTPS
- 优先使用
Authorization请求头,而不是查询参数(避免 Token 被记录到日志) - 使用 Cookie 时设置
HttpOnly和Secure标志 - 在登录端点结合
limit-req防止暴力破解 - 结合
ip-restriction增加网络层安全性
故障排查
| 现象 | 原因 | 修复方式 |
|---|---|---|
| 登录时返回 400 "appid is missing" | 登录请求体缺少 appid | 包含 appid 字段 |
| 400 "appid not found" | 没有配置使用该 appid 的消费者 | 创建 appid 匹配的消费者 |
| 每个请求都 返回 401 | Token 已过期或传递位置不正确 | 重新登录获取新 Token,并检查 Token 位置 |
| 403 "ERR_ACCESS_DENIED" | 用户在 Wolf 中没有对应 URL + 方法权限 | 在 Wolf 控制台中配置权限 |
| 500 "request to wolf-server failed" | Wolf 服务器停机或不可达 | 检查 Wolf 服务器 URL 和连通性 |
| 登录端点返回 404 | 未通过 public-api 暴露 | 为登录 URI 创建启用 public-api 插件的路由 |
本文根据 api7/a6 仓库中的 a6-plugin-wolf-rbac/SKILL.md 生成。可在 AI Agent Skills 页面浏览全部 Skill。