返回知识中心
平台

Web Push 订阅生命周期与隐私

从权限和 endpoint 创建,到轮换、退订清理与隐私保留策略,完整管理 Push API 订阅。

BotBrowser Team

文档中心

想直接进入 平台 文档吗?

这篇文章属于知识中心的指南库。若你要步骤化配置、参考说明和持续更新,请直接进入对应 docs 分区。

Web Push 从权限与订阅创建,到 endpoint 轮换、退订清理和隐私复核的生命周期

Web Push 不是永久权限,也不是稳定的用户标识。浏览器可以授予通知权限、为 service worker 创建带有 endpoint 和密钥的订阅、轮换该订阅,随后再删除它。BotBrowser 可以在经授权的受控 profile 中保留声明的权限状态,帮助团队检查自己的应用流程;它不会授予权限、发送消息、替用户决定是否需要通知,也不会代表应用从 push 服务删除 endpoint。Permissions Policy 指南将策略允许与这里记录的权限状态分开。

Push API 规范、MDN Push API 参考 和 Service Workers 规范描述了浏览器对象与事件。对应的 BotBrowser permissions 文档说明了权限状态作为 profile 输入的用途;该页面不覆盖订阅生命周期、失效 endpoint 发现、unsubscribe() 后清理,以及 endpoint 和密钥的隐私保留边界。

TL;DR

  • 将 Notification.permission、PushSubscription 和服务器记录视为三个相关但不同的状态。
  • 只有在用户看得到的操作和明确的通知说明之后,才创建订阅。
  • endpoint 和公钥只为声明的目的保存,并记录负责人、期限与删除路径。
  • 对 pushsubscriptionchange、发送失败、退出登录、关闭账户和 unsubscribe() 做对账,不要假设订阅永久有效。
  • endpoint 是可关联的路由能力,不是身份主键。

目录

区分权限、订阅与投递状态

Notifications API 暴露权限状态,而 Push API 为 service worker registration 创建 PushSubscription。两者不能互换。Notification.permission === "granted" 只表示当前上下文允许使用通知;它不表示已经有订阅、用户已经登录,或 push provider 一定会投递。即使权限仍为 granted,也可能没有订阅。

应用记录至少要有三套状态。权限可以是 default、denied 或 granted;订阅可以是 none、active、rotating、unsubscribed 或 expired;投递可以根据 provider 响应标为 unknown、accepted、rejected 或 stale。一个 push_enabled 字段会混淆责任,也会让清理过程无法审计。

registration.pushManager.getSubscription() 返回订阅或 null。null 只是这个 registration、origin 和 scope 的观察结果,不能证明用户从未在别的上下文订阅。读取权限和订阅后再说明下一步,不要猜测身份。最小记录可以包括随机内部 ID、origin、service worker scope、用于去重的不可逆引用、协议所需公钥、创建与最近观察时间、生命周期状态和删除原因。不要把完整 endpoint 放进分析维度或 URL。

支持人员需要区分几种情况:权限已授予但 worker 尚未就绪;provider 拒绝最近的 endpoint;用户本地退订但服务器行仍然 active。对应负责人可能是浏览器、页面、worker、provider 或数据库。浏览器权限与指纹文章说明权限状态不是人的标识;endpoint 长期保留则会产生额外的关联风险。

在明确意图下创建订阅

调用 subscribe() 前,说明通知类别、频率、关闭方式,以及 endpoint 是否会与账号或设备上下文关联。不要在页面加载、隐藏定时器或无关功能打开时触发订阅。先注册 service worker,等待 navigator.serviceWorker.ready,确认 scope,再调用 getSubscription()。如果没有现有订阅,展示明确的用户选择。

启用控件必须有同样清楚的关闭路径。“启用订单通知”比“允许通知”更具体。设置页要显示应用状态;权限被拒绝时,应说明需要到浏览器设置处理。应用开关不能撤销浏览器级拒绝。

applicationServerKey 将订阅关联到服务公钥。只有在计划好的迁移中才切换 key version,并在服务器保存版本号,不要保存私钥。通过认证且可重复的请求发送 endpoint、所需公钥、origin 和短期 request ID。endpoint 是投递能力,不是账号所有权证明。

把拒绝、service worker 不可用、上下文政策阻止、provider 错误和应用响应错误分开处理。失败时保留用户正在做的事情,必要时提供应用内更新。不要不断重新打开已拒绝的 prompt,也不要把未脱敏 endpoint 或异常字符串送入无关的遥测系统。

建模 endpoint 轮换和 service worker 事件

订阅 endpoint 可能改变。service worker 全局作用域中的 pushsubscriptionchange 是对账信号,但不能假设所有浏览器都会在每种情况下触发。worker 可以获取当前订阅、通过有界且认证的请求更新服务器,并把旧记录标为待复核。如果没有可用的新订阅,应保留 unknown rotation,由之后的一次明确页面访问完成对账。

轮换不等于新用户。原因可能是浏览器维护、provider 政策、key 修改、profile 重置或 worker 替换。用短期迁移引用把新记录关联到旧应用记录,再重新检查账号和目的;新 endpoint 被接受后,尽快让旧 endpoint 退出 active 投递。

provider 返回 endpoint 不存在时,可以将记录设为 stale 并停止发送。临时错误应按 provider 的规则有限重试,不能立即删除。发送成功也不证明用户看见或仍然需要通知;投递确认与用户互动必须分开。

更新后的 service worker 可能改变 push 和 notificationclick 处理方式。要将记录 schema 与 worker 激活协调起来;如果旧服务器记录缺少新字段,应保留兼容路径。Service worker 更新文章讨论客户端版本协调;Service worker 缓存生命周期说明为什么激活和存储清理需要明确负责人。

清理退订和账户转换

PushSubscription.unsubscribe() 会从浏览器的 push manager 删除订阅并返回 boolean。返回 true 不会删除服务器记录、provider 队列或外部日志。应用还要发送独立的认证禁用请求,并处理客户端离线导致的延迟。

清理接口要幂等:验证账号所有权、将记录标为 inactive,并从投递存储移除 endpoint 与密钥。为了防止意外重新激活,可以短期保留只含随机 ID、时间和原因的 tombstone,但不要仅为方便而保留完整 endpoint。

退出登录和关闭账户不是一回事。退出可以停止当前会话的账号投递,同时保留用户在另一个获准账号中的设备选择;关闭账户则应按保留政策撤销该账户的所有记录并删除应用副本。关闭标签页或停止 worker 都不能证明上述任何动作已经完成。

如果浏览器本地操作成功但网络失败,只保存会过期的最小对账标记,并在下次认证访问时重试。如果服务器已禁用记录而浏览器操作失败,要说明本地清理仍待完成。只有在掌握每个受控系统的证据时,才可以说“已在所有地方删除”。

最小化 endpoint 隐私与保留

不透明的 endpoint 仍然是可以关联的路由值。应把 endpoint 和公钥视为个人数据或敏感的假名标识,并把完整值放在访问受限的投递存储中。分析只需要生命周期事件、目的类别和不可逆内部 ID;支持视图只显示最近时间、状态、key version 和必要的脱敏后缀。不要把 endpoint 放进截图、URL、客户端日志或长期导出。

保留期限应由用户目的决定。只要用户选择接收声明类别且服务仍需要投递,可以保持 active;stale、unconfirmed 或 unsubscribed 记录应快速过期。目的结束、账户关闭或期限到达后,删除或不可逆脱敏 endpoint 与密钥,只保留删除原因。备份流程也要覆盖这些字段,否则主表删除并不等于副本删除。

通知内容同样要最小化。通知可能出现在共享锁屏上,push provider 也可能处理元数据。优先发送短期 opaque reference,让用户在正常授权的应用页面中读取详细内容。不要把 “subscribed”“rotated”“clicked”“unsubscribed” 与其他浏览器信号拼成长期行为画像。请在策略中明确 retentionUntil 字段和 accountClosed 触发条件,方便核对期限。

使用基于证据的生命周期记录

记录声明的目的、origin、service worker scope、permission 观察、subscription 状态、key version、脱敏 record ID、应用动作、时间和 retention deadline。可用于文档的最小形状如下:

{
  "purpose": "order-status",
  "origin": "https://shop.example",
  "serviceWorkerScope": "/app/",
  "permission": "granted",
  "subscriptionState": "active",
  "keyVersion": "v2",
  "recordId": "psr_7f2c",
  "lastReconciledAt": "2026-10-25T14:00:00Z",
  "retentionUntil": "2026-11-24T14:00:00Z",
  "nextAction": "send"
}

这些值只是 fixture 形状,不代表真实订阅。如果 permission 是 granted、subscription 是 none,就解释状态并提供明确 opt-in;如果 subscription 是 active 但投递是 stale,停止发送并对账;如果是 unsubscribed,删除 active 路由数据,不要静默重新订阅;如果超过 retention,删除记录并要求新的用户决定。

观察结果含义负责人安全下一步
permission=granted、subscription=null浏览器允许通知,但本地没有订阅页面与用户解释并提供明确 opt-in
subscription=active、provider 返回 gone投递路线已经失效投递服务标为 stale 并对账
unsubscribe() 返回 true、服务器行仍 active本地完成,服务器清理待完成应用 API重试幂等禁用请求
permission=denied、服务器行 active浏览器选择与投递意图冲突用户与应用停止发送并指导浏览器设置
retention deadline 已过目的结束或记录被放弃数据负责人删除 endpoint 和密钥

BotBrowser 支持在经授权的 profile 中复现声明的 permission 输入,并打开自有页面让应用记录 getSubscription() 等状态变化;它不会召唤原生 prompt、替用户选择、创建用户订阅、查看 provider 私有队列、保证 pushsubscriptionchange 发生,或证明所有外部系统都已删除。它适合做范围受限的兼容性观察。

常见问题

granted 权限是否代表用户已经订阅?

不是。应用仍要创建 PushSubscription、提交服务器注册并检查自己的记录。

endpoint 是设备指纹吗?

它不能证明设备或个人,但可以连接投递事件。因此要限制访问、保留期限和与其他信号的关联。

unsubscribe() 之后应该做什么?

把浏览器结果和服务器清理分开处理,调用认证且幂等的禁用接口,删除 active endpoint 与 key。没有 provider 证据时,不要承诺队列或日志也被清除。

endpoint 轮换是否应该创建新账号?

通常不应该。创建新的投递行并暂时关联旧应用记录,重新检查账号和目的,再让旧 endpoint 退出 active。

BotBrowser 能为 profile 开启 Web Push 吗?

它可以为授权的受控检查保留声明权限,但不会授予权限、创建用户订阅或保证投递。

来源

实践结论

把 Web Push 建模为生命周期:permission 开启浏览器能力,service worker registration 拥有订阅,服务器授权投递,清理动作结束目的。对账 endpoint 轮换、provider 失败、权限变化、退出登录、关闭账户和 unsubscribe();不要把 endpoint 与 key 放入分析或身份系统。BotBrowser 可以重复经授权的权限输入,但用户意图、投递状态和删除责任仍属于应用及其 push provider。

#Web Push#Push Api#Service Workers#权限#隐私

本文属于指南: Web 平台能力面:一致性复核地图

让 BotBrowser 从研究走向生产

先用这些指南理解模型,再进入跨平台验证、隔离上下文和面向规模化的浏览器部署。