8.2 KiB
IAM Service — Scalar 调用顺序指南(v0.1.0)
Authentication(认证方式)
本服务使用 JWT Bearer Token:
- 登录成功后拿到
access_token - 后续请求在 Header 中带:
Authorization: Bearer <access_token>
- 租户上下文:
- 保护接口默认从 Token claim 的
tenant_id推导租户 - 可选兼容
X-Tenant-ID: <uuid>,若同时提供 Header 与 Token,则必须一致,否则返回 403
- 保护接口默认从 Token claim 的
访问令牌(JWT)除 tenant_id/user_id/roles/permissions 外,还包含:
apps:租户已开通应用列表(如["cms","tms"])apps_version:租户 enabled_apps 版本号(用于客户端判断是否需要刷新会话)
OpenAPI/Scalar 可配置参数(环境变量)
为方便本地调试与演示,服务会在生成 OpenAPI 文档时,将部分 Header 参数的示例值按环境变量动态注入(影响 /scalar 展示,不影响服务鉴权逻辑):
IAM_DOCS_DEFAULT_TENANT_ID:默认租户 ID(用于X-Tenant-IDHeader 的 example)- 未设置时默认:
11111111-1111-1111-1111-111111111111 - 可选强制:
IAM_DOCS_REQUIRE_TENANT_ID=1(未设置则启动时直接失败)
- 未设置时默认:
IAM_DOCS_DEFAULT_TOKEN:默认 Token(用于AuthorizationHeader 的 example)- 可填写裸 JWT 或
Bearer <jwt>;裸 JWT 会自动补齐Bearer - 未设置时默认:
Bearer <access_token> - 可选强制:
IAM_DOCS_REQUIRE_TOKEN=1(未设置则启动时直接失败)
- 可填写裸 JWT 或
通用响应结构
成功响应:
{ "code": 0, "message": "Success|Created|Accepted", "data": {}, "trace_id": null }
错误响应(示例):
{ "code": 20006, "message": "Missing authorization header", "details": null, "trace_id": null }
常见错误码(节选):
- 20006:缺少必要 Header(如 Authorization)
- 20003:无权限(403)
- 20005:账号或密码错误
- 30000:请求参数错误(400)
- 30002:资源不存在(404)
- 30003:资源冲突(409)
- 40000:请求过于频繁(429)
- 10001:数据库错误(500)
Step-by-step(可复制流程)
Step -1:数据库初始化 / 迁移(开发/测试/生产)
本服务新增了“租户已开通应用(enabled_apps)”与“平台超级管理员(SuperAdmin)”能力,对应数据库新增表:
appstenant_entitlementstenant_enabled_apps_history
推荐使用版本化迁移脚本初始化与升级:
- 执行迁移:
scripts/db/migrate.sh - 执行校验:
scripts/db/verify.sh - 回滚(按版本):
scripts/db/rollback.sh
本仓库同时保留开发用的一键重建脚本:scripts/db/rebuild_iam_db.sh(会清库重建,不适合生产)。
Step 0:创建租户(可选)
POST /tenants/register
- Tag:
Tenant - Header:无
- Body:
{ "name": "Tenant A", "config": { "theme": { "primary": "#1d4ed8" } } }
成功(201)从 data.id 取出租户 ID:
{ "code": 0, "message": "Created", "data": { "id": "<tenant_id>", "name": "Tenant A", "status": "active", "config": {} }, "trace_id": null }
下一步依赖:tenant_id(用于注册/登录时的 X-Tenant-ID)。
Step 0.1:平台超级管理员(可选,但推荐先完成)
数据库已内置平台租户(Platform tenant):
tenant_id = 00000000-0000-0000-0000-000000000001
在平台租户下注册首个用户,将自动获得平台级权限(用于管理各租户 enabled_apps):
POST /auth/register
- Tag:
Auth - Header:
X-Tenant-ID: 00000000-0000-0000-0000-000000000001 - Body:
{ "email": "superadmin@example.com", "password": "securePassword123" }
Step 1:注册用户
POST /auth/register
- Tag:
Auth - 必需 Header:
X-Tenant-ID: <tenant_id> - Body:
{ "email": "user@example.com", "password": "securePassword123" }
成功(201)从 data.id 取出 user_id(后续可用于用户管理接口):
{ "code": 0, "message": "Created", "data": { "id": "<user_id>", "email": "user@example.com" }, "trace_id": null }
Step 2:登录获取访问令牌(Authentication 入口)
POST /auth/login
- Tag:
Auth - 必需 Header:
X-Tenant-ID: <tenant_id> - Body:
{ "email": "user@example.com", "password": "securePassword123" }
成功(200)从 data.access_token 取出访问令牌:
{ "code": 0, "message": "Success", "data": { "access_token": "<jwt>", "refresh_token": "<opaque>", "token_type": "Bearer", "expires_in": 900 }, "trace_id": null }
下一步依赖:access_token。
Step 3:获取当前租户信息(Tenant)
GET /tenants/me
- Tag:
Tenant - 必需 Header:
Authorization: Bearer <access_token> - 可选 Header:
X-Tenant-ID: <tenant_id>(如提供必须与 token tenant_id 一致)
成功(200):
{ "code": 0, "message": "Success", "data": { "id": "<tenant_id>", "name": "Tenant A", "status": "active", "config": {} }, "trace_id": null }
Step 4:查看当前用户权限(Me)
GET /me/permissions
- Tag:
Me - 必需 Header:
Authorization: Bearer <access_token>
成功(200):
{ "code": 0, "message": "Success", "data": ["tenant:read","tenant:write"], "trace_id": null }
下一步依赖:确认具备目标权限(例如 user:read / role:read)。
Step 4.1:平台层设置租户已开通应用(SuperAdmin)
该能力仅允许拥有平台级权限的用户调用:
iam:tenant:enabled_apps:readiam:tenant:enabled_apps:write
4.1.1 查询某租户 enabled_apps
GET /platform/tenants/{tenant_id}/enabled-apps
- Tag:
Tenant - Header:
Authorization: Bearer <access_token>(平台租户下登录得到的 token)
4.1.2 设置某租户 enabled_apps(全量覆盖,幂等)
PUT /platform/tenants/{tenant_id}/enabled-apps
- Tag:
Tenant - Header:
Authorization: Bearer <access_token> - Body:
{ "enabled_apps": ["cms", "tms"], "expected_version": 0 }
说明:
expected_version可选,用于并发控制;不匹配会返回 409。- 登录签发 token 时会自动把
apps/apps_version注入到 JWT,并对permissions按 enabled_apps 过滤。 enabled_apps必须是“应用注册表 apps 表”中存在且status=active的应用 ID;若传入未知/已下线应用(例如dms),接口会返回 400。
enabled_apps 维护建议:
- 新增应用:通过数据库迁移向
apps(id,name,description,status)插入一行(id推荐全小写短标识,如cms/tms)。 - 下线应用:将
apps.status置为非active(例如disabled),之后将无法再被设置进任何租户的 enabled_apps。 - 查询可用应用(示例 SQL):
SELECT id, name, status FROM apps ORDER BY id;
Step 5:列出用户(User)
GET /users?page=1&page_size=20
- Tag:
User - 必需 Header:
Authorization: Bearer <access_token> - 分页规则:
page默认 1,必须 >= 1page_size默认 20,范围 1..=200
成功(200):
{ "code": 0, "message": "Success", "data": [{ "id": "<user_id>", "email": "user@example.com" }], "trace_id": null }
Step 6:列出角色(Role)
GET /roles
- Tag:
Role - 必需 Header:
Authorization: Bearer <access_token>
成功(200):
{ "code": 0, "message": "Success", "data": [{ "id": "<role_id>", "name": "Admin", "description": "..." }], "trace_id": null }
Step 7:用户-角色绑定(User)
用户注册后默认无角色;通常由具备 user:write 的管理员进行角色分配。
7.1 查询用户角色列表(需要 user:read)
GET /users/{id}/roles
- Tag:
User - Header:
Authorization: Bearer <access_token>
7.2 设置用户角色(全量覆盖,幂等;需要 user:write)
PUT /users/{id}/roles
- Tag:
User - Header:
Authorization: Bearer <access_token> - Body:
{ "role_ids": ["<role_id_1>", "<role_id_2>"] }
说明:
role_ids必须全部属于当前租户,否则返回 400。
限流说明(Auth)
/auth/login:约 2 req/s,burst 10(同一 IP)/auth/register:约 1 req/s,burst 5(同一 IP)- 触发后返回:HTTP 429 +
code=40000