pushmanager.subscribe() 返回的 subscription 对象必须立即通过 fetch post 发送到后端 api 持久化存储,不可存于前端 localstorage;后端需原样保存 endpoint、keys.p256dh、keys.auth 三个字段为 text 类型,避免 json 重解析或 base64 截断/修改,确保推送时解密成功。

PushManager.subscribe() 返回的 subscription 对象怎么持久化?
浏览器端调用 PushManager.subscribe() 后拿到的 subscription 是一次性有效凭证,必须立刻存到后端,不能只存在前端 localStorage 或 sessionStorage 里——它包含加密密钥(keys.p256dh 和 keys.auth),且服务端推送时必须原样使用,稍有修改(比如 JSON 序列化时字段顺序变动、空格、换行)就会导致解密失败。
实操建议:
文章转信息图。将文章/笔记转化为手机可读的 HTML 信息图,自动匹配视觉风格。触发场景:文章转图、笔记转图、信息图、转小红书图、做张图、可视化这篇文章、文生图。
- 前端拿到
subscription后,立即用fetchPOST 到你自己的 API(如/api/subscribe),body 为JSON.stringify(subscription) - 后端接收时不要做任何 JSON 重解析或字段重组,直接提取
endpoint、keys.p256dh、keys.auth三个字段存入数据库,字段类型建议用 TEXT(避免 MySQL 的 utf8mb4 对 base64 字符截断) - 特别注意:Chrome 有时返回的
endpointURL 带有查询参数(如?encoding=...&encryption=...),必须完整保留,删掉会导致 400 错误
为什么发送 Push 时总收到 404 或 410?
这两个错误说明订阅已失效,不是代码写错了,而是 endpoint 过期了。常见原因有:用户手动取消订阅、浏览器清除站点数据、设备重装系统、Chrome 在后台长时间不活动后自动回收 push service 连接。
实操建议:
- 每次推送前,先用
fetch向subscription.endpoint发一个 HEAD 请求(不用带 body),检查状态码:410 表示永久失效,404 多数是临时不可达但也可按失效处理 - 后端应建立定时任务(如每天一次),批量验证所有 endpoint 的可用性,并把返回 410/404 的记录标记为
invalid或直接删除 - 前端在页面加载时可调用
registration.pushManager.getSubscription()检查当前是否还有有效 subscription;若返回 null,说明已丢失,需重新调用subscribe()
后端用 webpush 库发消息,为什么提示“Invalid encryption key”?
这是 Node.js 环境下最常踩的坑:webpush 库(如 web-push)要求传入的 p256dh 和 auth 必须是 base64url 编码(无填充、无换行、+// 替换为 -/_),但浏览器返回的是标准 base64,且有些后端存储时自动做了 URL decode 或 trim,导致密钥损坏。
实操建议:
- 存库前不做任何 base64 转换,原样存字符串;发消息时再用工具函数转成 base64url —— 例如 Node.js 可用:
function toBase64URL(str) { return str.replace(/\+/g, '-').replace(/\//g, '_').replace(/=/g, ''); } - 检查
p256dh长度:标准值应为 88 字符(base64 编码后的长度),若存库后变成 86 或 92,大概率被截断或补了等号 - 用
web-push的getVapidHeaders()生成的 VAPID 公钥,必须和前端注册时传入的公钥完全一致(包括是否带-----BEGIN PUBLIC KEY-----头尾)
如何安全地管理 VAPID 私钥和公钥?
VAPID 私钥一旦泄露,攻击者就能以你的名义向任意订阅用户发推送,等同于账号被盗。它绝不能硬编码在前端 JS、不能提交进 Git、也不能放在 Web 根目录下可被直接访问。
实操建议:
- 用
web-push generate-vapid-keys生成密钥对后,私钥(privateKey)只存后端环境变量(如process.env.VAPID_PRIVATE_KEY)或密钥管理服务(AWS KMS / HashiCorp Vault) - 公钥(
publicKey)可以安全暴露给前端,但不要直接写死在 HTML 里;建议由后端接口返回(如GET /vapid-public-key),方便后续轮换 - 如果用 Nginx/Apache,确保
.env、keys/目录被明确禁止 HTTP 访问(Nginx 示例:location ~ ^/(.env|keys/) { deny all; })
前端入门到VUE实战笔记:立即使用
在学习笔记中,你将探索 前端 的入门与实战技巧!










