diff --git a/api/health b/api/health index 344b1d7..98c9026 160000 --- a/api/health +++ b/api/health @@ -1 +1 @@ -Subproject commit 344b1d7332195ea2d30a6d71b19f15f21ed4b365 +Subproject commit 98c902648527cd2657280107050c994bdbbb4de9 diff --git a/api/user b/api/user index 70307d4..058e913 160000 --- a/api/user +++ b/api/user @@ -1 +1 @@ -Subproject commit 70307d4eb89d6735df7233cccbfb324c7b123726 +Subproject commit 058e9135ae6e4762d0ea5e4da171de3e27c57967 diff --git a/doc/backend-architecture.md b/doc/backend-architecture.md new file mode 100644 index 0000000..b6009ce --- /dev/null +++ b/doc/backend-architecture.md @@ -0,0 +1,72 @@ +# ws_health 后端架构与优化方案 + +> 更新时间:2026-08-30 + +## 一、当前结构 + +``` +d:\work\ws_health +├── api/ # 所有后台服务,每类服务一个目录,各自独立部署 +│ ├── health/ # 陪诊业务服务(订单/健康档案/资源/WS AI 聊天) +│ │ ├── HTTP :9004 # REST(koa) +│ │ └── WS :9005 # WebSocket(AI 聊天,Agent 按 userId 缓存) +│ └── user/ # 用户服务(注册/登录/token 鉴权/微信登录) +│ └── HTTP :9010 +├── ui/ # 小程序端 +│ ├── wxapp_escort/ # C 端 +│ └── wxapp_escort_admin/ # 管理端 +└── doc/ +``` + +- **网关**:nginx 按路径转发(`/health → 9004`、`/user → 9010`、`/ws → 9005`),参见 `api/health/nginx_site.txt` +- **数据库**:共用同一 MongoDB 实例,**按服务分库**(user 用 `eiot_user` 库,health 用自己的库),各自独立连接配置 +- **认证体系**:token 单点在 user 服务(DB 存 sha256 哈希);health 服务通过 HTTP 实时调用 `/user/userInfo` 校验 +- **技术栈**:Node/Koa/Mongoose;AI 聊天基于 LangChain Agent(DeepSeek/Tavily/百度地图) + +## 二、架构结论 + +服务按目录拆分 + nginx 路由 + 分库的方案,**对中等 HTTP 流量(日请求百万级内、团队 3~10 人)完全够用**,属于标准的模块化单体 → 轻量微服务路径。 + +分库优于表前缀:边界清晰、索引不冲突、无历史包袱;量大时可平滑迁移到独立实例。 + +## 三、已完成的安全加固(2026-08-30 code review 后修复) + +### health 服务 +- 补齐 `findRecordsByAttendant`(原接口必然 500) +- escort-record / health-profile 全部路由挂载鉴权中间件(token → user 服务校验) +- `GET /escort-record/my` 强制按登录用户过滤(修 IDOR);新增 `GET /escort-record` 供管理端查全部 +- create/update 白名单过滤(兼容点号路径);连接日志脱敏;WS 聊天强制 token 校验、断连保护 + +### user 服务 +- 修复两个账号接管漏洞:匿名 `userInfo(userId)` 不再返回 `security.token`;`wxSignin` 不再信任客户端直传手机号绑定/覆盖已有账号(新增 `phoneCode` 服务端验证) +- `auth()` 中间件正式挂载;token 改 sha256 哈希入库(兼容旧明文自动迁移) +- 登录失败 ≥10 次自动锁定;微信 access_token 进程内缓存(防配额耗尽) +- `userList` 补 total、pageSize 上限 200 + +### 遗留手动事项 +1. **轮换凭证**:MongoDB 密码、微信 AppSecret(user 服务 conf.json)、`.env` 内 3 个 API key 均已入 git 历史;`.gitignore` 已补,需 `git rm --cached conf.json .env` 并更换凭证 +2. 锁定账户解锁目前需手动改库(`status.account: "normal"` + 重置 `failedLoginAttempts`),后续可加管理端解锁接口 + +## 四、优化方案(按优先级) + +### 1. ✅ health 鉴权调用加缓存(2026-08-30 已完成) +- 新增 `api/health/utils/user_service.js`:token→user 进程内缓存,**TTL 5 分钟** + - LRU 上限 2000 条,防止无限增长 + - 无效 token 负缓存 60 秒,防止伪造 token 打爆 user 服务 + - 网络异常不缓存,直接走降级路径 +- `requireAuth`(REST)与 WS 聊天的 `getUserInfo` 统一走该缓存,每请求不再实时调用 user 服务 +- 已知代价:**登出/账户锁定在 health 侧最多延迟 5 分钟生效**(user 服务自身接口即时生效) +- 中期规划:user 服务签发 JWT(短 access 无状态 + refresh 可撤销,Redis 黑名单兜底),之后新模块接入鉴权零成本;在引入"每请求查 Redis"的方案时,直接用不透明 token 存 Redis 即可,无需 JWT + +### 2. 内存态组件在水平扩容前外移 Redis +以下均为单进程内存态,单实例部署没问题;nginx 挂多实例后失效: +- user 服务限流(IP+路径维度) +- user 服务微信 access_token 缓存 +- health 服务 WS Agent 缓存(现为 LRU 上限 100) + +### 3. 配置统一 +两个服务各一份 conf.json,Mongo 连接信息重复、凭证轮换需改多处。建议统一到服务器级 `.env`,服务内只读环境变量;`.env`/`conf.json` 均已加入 .gitignore。 + +### 边界提醒 +- **跨服务事务**:目前无需求;将来"订单+支付+用户"强一致场景用 API 补偿/异步消息,不上分布式事务 +- **表前缀方案已放弃**:同库前缀隔离长期会互相踩字段,分库无此问题