Files
Web_BAI_Manage_ApiServer/pocket-base/spec/changes.2026-03-23-pocketbase-hooks-auth-hardening.md
XuJiacheng 02d5686c7b feat: 完善微信认证功能,新增用户资料更新与token刷新接口
- 新增 userService.js,包含用户认证、资料更新、token 刷新等功能
- 新增 wechatService.js,处理微信API交互,获取openid和手机号
- 新增 appError.js,封装应用错误处理
- 新增 logger.js,提供日志记录功能
- 新增 response.js,统一成功响应格式
- 新增 sanitize.js,提供输入数据清洗功能
- 更新 OpenAPI 文档,描述新增接口及请求响应格式
- 更新 PocketBase 数据库结构,调整用户表字段及索引策略
- 增强错误处理机制,确保错误信息可观测性
- 更新变更记录文档,详细记录本次变更内容
2026-03-24 10:36:19 +08:00

4.8 KiB
Raw Blame History

OpenSpec 变更记录PocketBase Hooks 认证链路加固

日期

  • 2026-03-23

范围

本次变更覆盖 pocket-base/ 下 PocketBase hooks 项目的微信登录、资料更新、token 刷新、认证落库、错误可观测性、索引策略与运行规范。


一、认证模型调整

1. 认证体系

  • 保持 PocketBase 原生 auth token 作为唯一正式认证令牌。
  • 登录与刷新响应统一通过 $apis.recordAuthResponse(...) 返回 PocketBase 原生认证结果。
  • authMethod 统一使用空字符串 '',避免触发不必要的 MFA / login alerts 校验。

2. Header 规则

  • 正式认证 Header 为:Authorization: Bearer <token>
  • 非标准 Header Open-Authorization 不属于本项目接口定义。
  • users_wx_openid Header 已从 active hooks 鉴权链路移除。

二、身份字段与数据模型约束

1. openid 作为唯一业务身份锚点

  • tbl_auth_users 仅保留 openid 作为微信身份锚点。
  • 业务逻辑中不再使用 users_wx_openid
  • 用户查询、token 刷新、资料更新均基于 auth record 的 openid

2. auth 集合兼容字段

由于 tbl_auth_users 当前为 PocketBase auth 集合,登录注册时为兼容 PocketBase 原生 auth 校验,新增以下兼容策略:

  • email 使用占位格式:<openid>@wechat.local
  • 自动生成随机密码
  • 自动补齐 passwordConfirm

说明:

  • 占位 email 仅用于满足 auth 集合保存条件,不代表用户真实邮箱。
  • 业务主身份仍然是 openid

3. 自定义字段可空策略

  • tbl_auth_users 的自定义字段目标约束为:除 openid 外,其余业务字段均允许为空。
  • 已将 schema 脚本中的 user_id 改为非必填。
  • 其余业务字段保持非必填。

三、查询与排序修复

1. 移除无意义的 created 排序

在 hooks 查询中,以下查询原先使用 '-created' 排序:

  • openid 查询用户
  • company_id 查询公司
  • users_phone 查询重复手机号

该写法在 PocketBase 当前运行场景下触发:

  • invalid sort field "created"

现已统一移除排序参数,改为空排序字符串,因为这些查询本质上均为精确匹配或去重检查,不依赖排序。


四、错误可观测性增强

1. 登录路由显式错误响应

POST /api/wechat/login 新增局部 try/catch

  • 保留业务状态码
  • 返回 { code, msg, data }
  • 写入 logger.error('微信登录失败', ...)

2. 全局错误包装顺序修正

  • routerUse(...) 全局错误包装提前到路由注册前。
  • 统一兼容 err.statusCode / err.status

3. auth 保存失败透传

新增 saveAuthUserRecord(record) 包装 $app.save(record)

  • 失败时统一抛出 保存微信用户失败
  • 附带 originalMessageoriginalData

目的:

  • 避免 PocketBase 默认 Something went wrong while processing your request. 吞掉具体原因。

五、数据库索引策略修复

1. users_phone 索引调整

原设计:

  • users_phone 唯一索引

问题:

  • 新用户注册阶段手机号为空,多个空值会触发唯一约束冲突,导致注册失败。

现调整为:

  • users_phone 普通索引

说明:

  • 手机号唯一性改由业务逻辑在资料完善阶段校验。
  • 允许多个未完善资料用户以空手机号存在。

六、接口契约同步结果

当前 active PocketBase hooks 契约如下:

  • POST /api/system/test-helloworld
  • POST /api/system/health
  • POST /api/wechat/login
  • POST /api/wechat/profile
  • POST /api/wechat/refresh-token

其中:

POST /api/wechat/login

  • body 必填:users_wx_code
  • 自动以微信 code 换取 openid
  • 若不存在 auth 用户则尝试创建 tbl_auth_users 记录
  • 成功时返回 PocketBase 原生 token + auth record + meta

POST /api/wechat/profile

  • Authorization
  • 基于当前 auth record 的 openid 定位用户
  • 服务端用 users_phone_code 换取手机号后保存

POST /api/wechat/refresh-token

  • Authorization
  • 直接基于当前 auth record 返回新的 PocketBase 原生 token

七、当前已知边界

  1. tbl_auth_users 为 PocketBase auth 集合,因此仍受 PocketBase auth 内置规则影响。
  2. 自定义字段“除 openid 外均可空”已在脚本层按目标放宽,但 auth 集合结构更新仍可能触发 PocketBase 服务端限制。
  3. 若线上仍返回 PocketBase 默认 400需要确保最新 hooks 已部署并重启生效。

八、归档建议

部署时至少同步以下文件:

  • pocket-base/bai-api-main.pb.js
  • pocket-base/bai_api_pb_hooks/
  • script/pocketbase.newpb.js

并在 PocketBase 环境中执行 schema 同步后重启服务,再进行接口验证。