# hotfix(user): /admin/auth/info 尊重 token role, SMS 登录强制 CUSTOMIZER

> **仓库**: HL (后端 hl-user-service)
> **关联 PR/Issue**: PR #2946 (#2918 跟进, 非新工单)
> **日期**: 2026-05-23
> **影响范围**: `/admin/auth/info` 响应 role 字段
> **接收方**: mmg (前端)
> **前端**: **无需改动** — 响应字段类型不变, 仅 role/roleName 值修正

---

## wx 实测反馈

SMS 登录后顶部用户信息显示「超级管理员」, 不是「定制师」。前端 admin 端登录后角色 badge 异常。

## 根因

PR #2920 (Closes #2918) 让 SMS 登录响应里 `role=CUSTOMIZER` 是对的, **但**:

- `getAdminInfo(adminId)` (Service) 默认按 `admin.currentRoleId` 算 activeRoleKey
- token 内嵌的 forced CUSTOMIZER 角色没传给 service
- 前端调 `/admin/auth/info` 重新拿到 currentRoleId 对应的 SUPER_ADMIN

## 修复

- `AdminAuthService.getAdminInfo` 新签名 `(adminId, tokenRole)`:
  - tokenRole=CUSTOMIZER 且 admin 真持有 CUSTOMIZER 角色 → activeRoleKey 强制 CUSTOMIZER
  - 否则按现有 currentRoleId 逻辑
  - **不污染 admin.currentRoleId 持久化** (SMS 是临时切角色)
- `AuthController.getAdminInfo` 从 `request.getAttribute("role")` 透传 token role

## 防御

`tokenRole=CUSTOMIZER` 但 admin 真实没 CUSTOMIZER 角色时 **NOT 强制**, 防止 token 纂改越权显示。

## API 行为对照

| token role | admin currentRoleId | admin 有 CUSTOMIZER | response.role | 说明 |
|---|---|---|---|---|
| 任意 | SUPER_ADMIN | - | SUPER_ADMIN | 旧逻辑 |
| CUSTOMIZER | SUPER_ADMIN | ✅ | **CUSTOMIZER** | **新, SMS 登录场景** |
| CUSTOMIZER | SUPER_ADMIN | ❌ | SUPER_ADMIN | 防御, 不信任 token |

前端无需改动, 响应字段类型不变。

## 测试服真测

部署 user-service (2026-05-23 10:58) 后:

| 场景 | response.role | response.roleName |
|---|---|---|
| SMS 登录 wx (持 SUPER_ADMIN+CUSTOMIZER 多角色) → /admin/auth/info | ✅ **CUSTOMIZER** | ✅ **定制师** |
| 密码登录 admin (SUPER_ADMIN) → /admin/auth/info | ✅ SUPER_ADMIN (不变) | ✅ 超级管理员 |

## 单测

- AdminAuthServiceTest **69** 全绿 (新加 2 个 case: SMS 强制 / 防御不强制)
- AuthControllerTest **9** 全绿 (新加 verify tokenRole 透传)

---

## 联系人

后端: wx (呼籁旅行)
前端: mmg
