FCM Admin:如何获取及生成Web应用用户的注册令牌?
关于Web推送注册令牌的获取与多用户生成指南
我来帮你理清Web推送中注册令牌的相关问题,结合你本地Express服务器的场景,一步步给你讲清楚:
一、如何获取当前客户端的注册令牌
注册令牌是前端通过浏览器的推送服务生成的,核心依赖Service Worker,具体步骤如下:
先配置前端的Service Worker
确保你的项目中有sw.js文件(Service Worker脚本),浏览器会用它来处理推送通知的接收逻辑。前端代码实现令牌获取流程
通过注册Service Worker、请求用户通知授权,最后订阅推送服务来拿到令牌,代码示例如下:// 注册Service Worker navigator.serviceWorker.register('/sw.js') .then(registration => { // 请求用户授权推送通知 return Notification.requestPermission() .then(permission => { if (permission === 'granted') { // 订阅推送服务,传入VAPID公钥验证服务器身份 return registration.pushManager.subscribe({ userVisibleOnly: true, // 浏览器要求推送必须对用户可见 applicationServerKey: urlBase64ToUint8Array('你的VAPID公钥') }); } }); }) .then(subscription => { // subscription.endpoint就是你要的注册令牌 console.log('当前客户端的注册令牌:', subscription.endpoint); // 把令牌发送到你的Express服务器保存 fetch('/save-token', { method: 'POST', body: JSON.stringify({ subscription, userId: '当前用户的唯一标识' // 比如用户ID、邮箱,用于后续关联 }), headers: { 'Content-Type': 'application/json' } }); }) .catch(error => { console.error('获取注册令牌失败:', error); }); // 辅助函数:将VAPID公钥从base64格式转为Uint8Array function urlBase64ToUint8Array(base64String) { const padding = '='.repeat((4 - base64String.length % 4) % 4); const base64 = (base64String + padding) .replace(/-/g, '+') .replace(/_/g, '/'); const rawData = window.atob(base64); return Uint8Array.from([...rawData].map(char => char.charCodeAt(0))); })这里的
VAPID公钥需要你提前生成(可以用web-pushnpm包的命令生成),用来验证你的Express服务器有权向该令牌对应的客户端发送推送。
二、为多个Web应用用户生成&管理注册令牌
每个用户的浏览器客户端会自动生成唯一的注册令牌,你只需要做好关联存储和管理:
令牌与用户的关联存储
当前端把令牌和用户标识(比如用户ID)发送到Express服务器后,你需要把这两者关联起来存在数据库中(比如MongoDB、MySQL)。比如可以设计一个user_tokens表,字段包括user_id、subscription(存储完整的推送订阅对象,包含令牌)。服务器端的推送处理示例
用web-pushnpm包来实现推送逻辑,代码示例:const webpush = require('web-push'); const express = require('express'); const app = express(); app.use(express.json()); // 配置VAPID密钥(公钥和私钥要和前端一致) const vapidKeys = { publicKey: '你的VAPID公钥', privateKey: '你的VAPID私钥' }; webpush.setVapidDetails( 'mailto:your-email@example.com', // 联系邮箱,推送服务可能会用来通知问题 vapidKeys.publicKey, vapidKeys.privateKey ); // 接收前端发送的令牌并保存 app.post('/save-token', (req, res) => { const { subscription, userId } = req.body; // 这里替换成你的数据库存储逻辑,比如: // UserToken.create({ userId, subscription }); res.status(200).send('令牌已成功保存'); }); // 给指定用户发送推送通知 app.post('/send-to-user', (req, res) => { const { userId } = req.body; // 从数据库中取出该用户所有的注册令牌(一个用户可能在多个设备登录) // const userSubscriptions = await UserToken.find({ userId }); const userSubscriptions = [/* 模拟从数据库拿到的订阅列表 */]; // 遍历所有令牌发送推送 userSubscriptions.forEach(subscription => { const payload = JSON.stringify({ title: '新通知', body: '这是给你的专属推送内容' }); webpush.sendNotification(subscription, payload) .catch(error => { // 如果推送失败,说明令牌已失效,从数据库中删除 // UserToken.deleteOne({ _id: subscription._id }); console.error('推送失败,已移除失效令牌:', error); }); }); res.status(200).send('推送任务已触发'); }); app.listen(3000, () => console.log('Express服务器运行在3000端口'));
额外注意事项
- 一个用户可能在多个设备(比如手机、电脑)登录你的应用,所以一个用户ID可能对应多个注册令牌,发送推送时要遍历所有令牌。
- 注册令牌可能会因为浏览器更新、用户清除缓存等原因失效,服务器要处理推送失败的情况,及时移除失效令牌。
- 必须确保用户授权了通知权限,否则无法获取注册令牌。
内容的提问来源于stack exchange,提问作者Bargain23
相关产品推荐
相关产品推荐

