78 lines
3.4 KiB
Markdown
Raw Permalink 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.

# 认证模块说明(`src/auth`
## 1. 目标
- 提供系统管理员创建、院内账号密码登录、B 端小程序手机号登录、C 端小程序手机号登录、身份查询。
- 使用 JWT 做认证,院内账号与 C 端小程序账号走两套守卫。
## 2. 核心接口
- `POST /auth/system-admin`:创建系统管理员(需引导密钥)
- `POST /auth/login`:院内账号密码登录,后台与小程序均可复用
- `POST /auth/login/confirm`:院内账号密码多账号确认登录
- `POST /auth/miniapp/b/phone-login`B 端小程序手机号登录
- `POST /auth/miniapp/b/phone-login/confirm`B 端同手机号多账号确认登录
- `POST /auth/miniapp/c/phone-login`C 端小程序手机号登录
- `GET /auth/me`:返回当前院内登录用户上下文
- `GET /c/patients/me`:返回当前 C 端登录账号绑定的患者基础信息
## 3. 院内账号密码登录流程
1. 前端提交 `phone + password``role``hospitalId` 都可以选传。
2. 若仅匹配到 1 个院内账号,后端直接返回 JWT。
3. 若匹配到多个院内账号,后端返回 `loginTicket + accounts` 候选列表。
4. 前端带 `loginTicket + userId` 调用确认接口获取最终 JWT。
## 4. 微信小程序登录流程
### B 端
1. 前端调用 `wx.login` 获取 `loginCode`
2. 前端调用手机号授权获取 `phoneCode`
3. 调用 `POST /auth/miniapp/b/phone-login`
4. 若手机号仅命中 1 个院内账号,后端直接返回 JWT。
5. 若命中多个院内账号,后端返回 `loginTicket + accounts`
6. 前端带 `loginTicket + userId` 调用确认接口拿最终 JWT。
### C 端
1. 前端同样传 `loginCode + phoneCode`
2. 后端先校验该手机号是否唯一命中 `Patient.phone`
3. 校验通过后创建或绑定 `FamilyMiniAppAccount`,并返回 C 端 JWT。
## 5. 鉴权流程
### 院内账号
1. `AccessTokenGuard``Authorization` 读取 Bearer Token。
2. 校验 JWT 签名、`id``iat` 等关键载荷字段。
3. 根据 `id` 回库读取 `User` 当前角色与组织归属。
4. 校验 `iat >= user.tokenValidAfter`,保证旧 token 失效。
### C 端小程序账号
1. `FamilyAccessTokenGuard``Authorization` 读取 Bearer Token。
2. 校验 C 端 token 的 `id + type=FAMILY_MINIAPP`
3. 根据 `id` 回库读取 `FamilyMiniAppAccount`
4. 将 C 端账号上下文注入 `request.familyActor`
## 6. 环境变量
- `AUTH_TOKEN_SECRET`
- `SYSTEM_ADMIN_BOOTSTRAP_KEY`
- `WECHAT_MINIAPP_APPID`
- `WECHAT_MINIAPP_SECRET`
## 7. 关键规则
- 后台 Web 与 B 端小程序都可以复用 `POST /auth/login` 做账号密码登录。
- 密码登录命中多个院内账号时,不再强制前端手填 `hospitalId`,改为后端返回候选账号供选择。
- B 端小程序登录复用 `User` 表,继续使用 `openId`
- B 端账号未绑定 `openId` 时,首次小程序登录自动绑定。
- 同一个 `openId` 可绑定多个院内账号,支持同一微信号切换多角色/多院区账号。
- 若目标院内账号已绑定其他微信号,仍需先在用户管理中清空该账号的 `openId` 再重新绑定。
- C 端账号独立存放在 `FamilyMiniAppAccount`
- C 端手机号必须唯一命中患者档案,否则拒绝登录。
- C 端登录后读取“我的信息”请调用 `GET /c/patients/me`,不要复用 `GET /auth/me`
- `serviceUid` 仅预留字段,本次不提供绑定接口。