Files
2026-02-02 16:47:37 +08:00

7.3 KiB
Raw Permalink Blame History

Client User Identity客户端用户标识建立用于 PUSH Token 绑定Spec

阶段高层规范spec

目标:在无账号体系或账号可选的前提下,为客户端生成一个稳定的“客户端用户标识”(下称 client_user_id),用于与 APNs/FCM 的 Push Token 建立绑定关系,便于后端精准下发 PUSH并支持 Token 变更/多设备/环境隔离等场景。


1. 背景与动机(摘要)

Push TokenAPNs device token / FCM registration token会发生变化重装、系统升级、重新授权、token rotate 等),且同一用户可能多设备。为了能稳定地“找到这个客户端实例/用户侧主体”并维护 Token 映射,需要一个与 Token 解耦、可持久化、不可推断的标识。


2. 目标Goals

  • 建立 client_user_id:客户端可生成并持久化一个稳定标识,作为后端 Push Token 绑定的主键之一。
  • Token 绑定可更新:支持 Token 变更时“同一 client_user_id 重新上报即可更新”。
  • 多设备兼容:同一个账号(若未来引入)可关联多个 client_user_id;一个 client_user_id 可存在多个 Token例如同设备多渠道/多应用包形态)时需可扩展。
  • 环境隔离dev/prod、iOS/Android、bundle id / package name 维度隔离,避免串绑。
  • 隐私友好不使用可追踪的硬件标识IMEI/IDFA/Android ID 等),不引入额外合规风险。

3. 非目标Non-goals

  • 不在本阶段引入完整账号体系、登录态、用户合并策略(如“同一人多设备合并为一个 user_id”
  • 不在本阶段强制接入设备证明App Attest/Play Integrity仅在安全章节提出可选增强方向。
  • 不定义具体数据库表结构与迁移脚本(属于 plan 阶段细化)。

4. 术语与对象Definitions

  • client_user_id:客户端生成并持久化的随机标识,代表“一个客户端安装实例(或一段时间内的用户侧主体)”,用于 Push 绑定。
  • push_token:系统/厂商下发的推送 tokeniOS/APNsAndroid/FCM可能变化。
  • account_id(可选):若未来存在登录账号,则用于把多个 client_user_id 归属到同一账号。

5. 关键决策:使用 UUID 做 client_user_id 是否合适?

结论:合适,推荐用随机 UUIDUUID v4 为默认),并把它当作后端与客户端都不解析的不透明字符串

5.1 为什么 UUID 合适

  • 唯一性足够v4 基于随机数,碰撞概率极低,满足全局唯一需求。
  • 不可推断:相较自增 ID不易被枚举相较设备硬件标识更隐私友好。
  • 跨端易实现iOS/Android/JS 都可稳定生成与序列化(字符串)。

5.2 需要明确的边界与注意事项

  • UUID 不等于“真实用户”:它更像“安装实例 ID”。用户重装/清数据后可能变化;这对 Push 绑定通常可接受(新装产生新 token 与新 id
  • 不要用设备硬件/系统可追踪 ID 替代:避免隐私与合规风险,也避免系统限制导致的不稳定。
  • 安全边界:如果后端完全信任客户端上报的 client_user_id,存在“伪造绑定”风险;应结合登录态或签名/证明(见第 9 节)降低滥用。

5.3 UUID 版本建议

  • 默认UUID v4实现最简单、兼容最好
  • 可选增强UUID v7有时间有序性利于日志/索引与写入局部性),但需要确保两端实现一致与依赖可控。

6. 客户端行为规范Client Contract

6.1 生成与持久化

  • 首次启动(或首次需要注册 Push 时):
    • 若本地不存在 client_user_id:生成一个新的 UUID字符串写入持久化存储。
    • 若已存在:直接复用。
  • 存储建议(不做强约束,但必须“尽量稳定”):
    • iOSKeychain
    • AndroidKeystore 保护的加密存储/SharedPreferences或等价方案
    • React Native/Expo使用安全存储能力例如 SecureStore/Keychain wrapper

6.2 Push Token 获取与上报时机

  • 在以下任一时机触发“注册/更新”:
    • 用户同意 Push 权限后获得 token
    • App 冷启动获取到 token含 token 变更)
    • 账号登录/登出(若存在账号)
    • 环境切换dev/prod或应用更新可选

7. 后端接口契约API Contract摘要

具体路由/鉴权方式在 plan 阶段落地;此处先定义字段语义与幂等行为。

7.1 注册/更新绑定

  • POST /v1/push/register
  • 请求体(最小集):
    • client_user_id: stringUUID 字符串)
    • platform: "ios" | "android"
    • push_token: string
    • app_id: stringbundle id / package name用于隔离
    • env: "dev" | "prod"
    • (可选)account_id: string
    • (可选)device_meta: { model, os_version, app_version, locale, timezone }
  • 行为要求(幂等):
    • push_token + env + app_id 维度做唯一性约束,避免重复记录。
    • 若同一 client_user_id 上报了新 token应更新/新增映射,旧 token 进入失效或保留历史(由实现决定,但必须可控)。

7.2 解绑(可选但建议)

  • POST /v1/push/unregister
  • 请求体:
    • client_user_id
    • platform
    • push_token(或让后端按 client_user_id 批量解绑,二选一)
    • app_id
    • env

8. 数据模型(逻辑约束)

最小需要表达的关系:

  • 一个 client_user_id 可对应 0..N 个 push_token考虑多端、多渠道、token rotate
  • 一个 push_token 在同一 env + app_id 下应只对应一个“当前归属”(避免重复推送)。
  • 若存在 account_id
    • 一个 account_id 可关联 0..N 个 client_user_id(多设备)。

9. 安全与滥用防护(高层约束)

  • 最小要求:接口需具备基本鉴权与频率限制(例如基于设备指纹/匿名 session/应用侧签名的任一组合),避免被脚本批量绑定垃圾 token。
  • 若存在登录态:推荐绑定写入需要登录态(或在登录后把 client_user_id 归属到 account_id),降低“抢绑”风险。
  • 可选增强(后续):接入 iOS App Attest / Android Play Integrity或对注册请求做一次性挑战签名。

10. 边界场景与处理原则

  • 用户拒绝 Push 权限:允许只有 client_user_id,不产生 token 绑定;后端不应报错。
  • token 变化:客户端重新调用 register,后端必须幂等更新,避免重复推送。
  • 重装/清数据client_user_id 变化可接受;若未来有 account_id,可在登录后重新建立关联。
  • 多环境dev/prod token 不可混用;必须以 env + app_id 隔离。

11. 验收标准Acceptance Criteria

  • 客户端能稳定生成并持久化 client_user_id(重复启动不变)。
  • 在 token 获取/变更后,调用注册接口可在后端建立(或更新)绑定关系,且接口幂等。
  • 同一 push_token 在同一 env + app_id 下不会产生多条“当前有效”绑定,避免重复推送。
  • 在用户拒绝 Push 权限、无 token 的情况下,不影响 App 正常使用与后续再次授权后的绑定。