- 更新微信登录、平台注册/登录、资料更新、token 刷新、认证落库等功能,统一使用 openid 作为全平台身份锚点。 - 新增平台用户注册和登录接口,支持手机号和密码认证。 - 实现系统级 token 刷新接口,支持通过微信 code 重新签发 token。 - 新增用户总数查询接口,返回 tbl_auth_users 表中的用户总数。 - 更新 OpenAPI 文档,反映新的接口和数据结构。 - 修改数据库结构,调整字段名称和索引。 - 新增页面示例,展示基本的 HTML 页面结构。
6.0 KiB
6.0 KiB
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_openidHeader 已从 active hooks 鉴权链路移除。
二、身份字段与数据模型约束
1. openid 作为唯一业务身份锚点
tbl_auth_users统一保留openid作为全平台身份锚点。- 微信用户:
openid = 微信 openid - 平台用户:
openid = 服务端生成的 GUID - 业务逻辑中不再使用
users_wx_openid。 - 用户查询、token 刷新、资料更新均基于 auth record 的
openid。
2. auth 集合兼容字段
由于 tbl_auth_users 当前为 PocketBase auth 集合,登录注册时为兼容 PocketBase 原生 auth 校验,新增以下兼容策略:
email使用占位格式:- 微信用户:
<openid>@wechat.local - 平台用户:
<openid>@manage.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):
- 失败时统一抛出
保存认证用户失败 - 附带
originalMessage与originalData
目的:
- 避免 PocketBase 默认
Something went wrong while processing your request.吞掉具体原因。
五、数据库索引策略修复
1. users_phone 索引调整
原设计:
users_phone唯一索引
问题:
- 新用户注册阶段手机号为空,多个空值会触发唯一约束冲突,导致注册失败。
现调整为:
users_phone普通索引
说明:
- 手机号唯一性改由业务逻辑在资料完善阶段校验。
- 允许多个未完善资料用户以空手机号存在。
六、接口契约同步结果
当前 active PocketBase hooks 契约如下:
POST /api/system/test-helloworldPOST /api/system/healthPOST /api/system/refresh-tokenPOST /api/platform/registerPOST /api/platform/loginPOST /api/wechat/loginPOST /api/wechat/profile
其中平台用户链路补充为:
POST /api/platform/register
- body 必填:
users_name、users_phone、password、passwordConfirm、users_picture - 自动生成 GUID 并写入统一身份字段
openid - 写入
users_idtype = ManagePlatform - 成功时返回 PocketBase 原生 token + auth record + meta
POST /api/platform/login
- body 必填:
users_phone、password - 仅允许
users_idtype = ManagePlatform - 前端使用手机号+密码提交
- 服务端内部仍通过 PocketBase 原生 password auth 返回原生 token
其中:
POST /api/wechat/login
- body 必填:
users_wx_code - 自动以微信 code 换取微信侧
openid并写入统一身份字段 - 若不存在 auth 用户则尝试创建
tbl_auth_users记录 - 写入
users_idtype = WeChat - 成功时返回 PocketBase 原生 token + auth record + meta
POST /api/wechat/profile
- 需
Authorization - 基于当前 auth record 的
openid定位用户 - 服务端用
users_phone_code换取手机号后保存
POST /api/system/refresh-token
- body 可选:
users_wx_code(允许为空) Authorization可选:- 若 token 仍有效:基于当前 auth record 续签
- 若 token 已过期:回退到微信 code 重签流程
- 若 token 已过期且未提供
users_wx_code,返回:token已过期,请上传users_wx_code - 返回精简结构,仅返回新 token(不返回完整登录用户信息)
- 属于系统级通用认证能力,不限定为微信专属接口
七、当前已知边界
tbl_auth_users为 PocketBaseauth集合,因此仍受 PocketBase auth 内置规则影响。- 自定义字段“除 openid 外均可空”已在脚本层按目标放宽,但 auth 集合结构更新仍可能触发 PocketBase 服务端限制。
- 若线上仍返回 PocketBase 默认 400,需要确保最新 hooks 已部署并重启生效。
八、归档建议
部署时至少同步以下文件:
pocket-base/bai-api-main.pb.jspocket-base/bai_api_pb_hooks/script/pocketbase.newpb.js
并在 PocketBase 环境中执行 schema 同步后重启服务,再进行接口验证。