You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

FCM Admin:如何获取及生成Web应用用户的注册令牌?

关于Web推送注册令牌的获取与多用户生成指南

我来帮你理清Web推送中注册令牌的相关问题,结合你本地Express服务器的场景,一步步给你讲清楚:

一、如何获取当前客户端的注册令牌

注册令牌是前端通过浏览器的推送服务生成的,核心依赖Service Worker,具体步骤如下:

  1. 先配置前端的Service Worker
    确保你的项目中有sw.js文件(Service Worker脚本),浏览器会用它来处理推送通知的接收逻辑。

  2. 前端代码实现令牌获取流程
    通过注册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-push npm包的命令生成),用来验证你的Express服务器有权向该令牌对应的客户端发送推送。

二、为多个Web应用用户生成&管理注册令牌

每个用户的浏览器客户端会自动生成唯一的注册令牌,你只需要做好关联存储和管理:

  1. 令牌与用户的关联存储
    当前端把令牌和用户标识(比如用户ID)发送到Express服务器后,你需要把这两者关联起来存在数据库中(比如MongoDB、MySQL)。比如可以设计一个user_tokens表,字段包括user_id、subscription(存储完整的推送订阅对象,包含令牌)。

  2. 服务器端的推送处理示例
    用web-push npm包来实现推送逻辑,代码示例:

    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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.25 06:34:23