liuyun d793d34cfc
Some checks are pending
CI / backend (push) Waiting to run
CI / frontend (push) Waiting to run
feat(auth): 平台超管租户切换(子模块 + openspec change)
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-10-12 00:02:52 +08:00

43 lines
2.2 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

## Context
JWT 载荷为 `{ sub, tenantCode, username, ver, sid }`;`RequestContext` 由 token 派生,`resolveAuth`/`buildContext`/`getMenus` 在**当前租户**内解析角色与 `isSuper`;`checkUserActive` 在**当前租户**内查用户。多租户隔离使平台超管(`touyun`)看不到 `demo` 租户数据。动机见 proposal.md - Why。
## Goals / Non-Goals
**Goals:**
- 平台超管切入任意租户,数据按目标租户过滤、权限超管绕过、审计归属保留真实超管。
**Non-Goals:**
- 不做普通用户/业务租户管理员的跨租户切换。
- 不做「切回上一个租户」的历史记录(重新选择即可)。
## Decisions
### D1 — 身份保留 + `super` 标志
JWT 增加 `super?: boolean`(仅切换接口签发 true)。`sub` 始终是平台超管真实 userId,`tenantCode` 为切入租户。切回 = 再次切换(切到 `touyun`)。
- **为什么不用「冒充目标租户管理员」**:会丢失超管真实身份,切回需重新登录,审计归属也错。
### D2 — `POST /auth/switch-tenant`
仅登录态;校验 `isPlatformSuperAdmin(userId)`(查 `touyun` 的 `user_role` 是否含 `super_admin`)+ 目标租户存在且 enabled;签发 `super:true` 新 token(沿用超管 `ver`,新 `sid`);记审计 `auth/switch-tenant`。
### D3 — `isSuper` 解析改为「平台租户为准」
`isPlatformSuperAdmin(userId)` = 平台租户 `user_role` 含 `super_admin`。`resolveAuth`/`buildContext`/`getMenus` 的 `isSuper = 当前租户含 super_admin || isPlatformSuperAdmin(userId)`。`checkUserActive` 对 `super` token 在**平台租户**查用户(因超管 userId 在 `touyun` 而非目标租户)。
### D4 — 前端顶栏切换
`permissionStore.super` 为真时显示「切换租户」下拉(列 `GET /tenants`);切换后 `auth` store 换 token、`reset` 菜单/字典/权限/页签,刷新进入目标租户上下文。
## Risks / Trade-offs
- **[super 标志被篡改]** → JWT 签名防篡改,且仅 switch 接口签发 `super:true`。
- **[切换后超管自身待改密]** → super token 仍走 `checkUserActive`,超管待改密时需先改密(可接受)。
## Migration Plan
无数据迁移;纯后端 + 前端。回滚即撤销。
## Open Questions
无。