2.2 KiB
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
无。