React Web应用基于FCM HTTP v1实现推送通知的步骤及OAuth令牌问题
使用FCM HTTP v1 API实现React Web推送通知(含OAuth令牌获取步骤)
一、OAuth访问令牌的获取说明与实现
FCM HTTP v1要求的OAuth访问令牌是服务端身份验证凭证,绝对不能在前端生成(会泄露敏感的服务账号密钥),必须在后端完成生成与管理。
获取Firebase服务账号密钥
- 登录Firebase控制台,进入目标项目的「设置」→「服务账号」
- 点击「生成新的私钥」,下载JSON格式的密钥文件,妥善存储(禁止提交到代码仓库或暴露给前端)
生成OAuth令牌的两种方式
方式1:使用Firebase Admin SDK(推荐,自动处理令牌缓存与刷新)
以Node.js后端为例:
const admin = require('firebase-admin'); // 导入下载的服务账号密钥 const serviceAccount = require('./path/to/your-service-account-key.json'); // 初始化Admin SDK admin.initializeApp({ credential: admin.credential.cert(serviceAccount) }); // 获取令牌(SDK自动缓存,有效期1小时,过期自动刷新) async function getAccessToken() { const credential = admin.credential.applicationDefault(); const token = await credential.getAccessToken(); return token.access_token; }
方式2:手动调用Google OAuth端点(不推荐,需自行处理JWT签名与过期)
如果不想用Admin SDK,可通过JWT签名生成令牌,以Node.js+jsonwebtoken+axios为例:
const jwt = require('jsonwebtoken'); const axios = require('axios'); const serviceAccount = require('./path/to/your-service-account-key.json'); async function generateOAuthToken() { // 构造JWT payload const payload = { iss: serviceAccount.client_email, scope: 'https://www.googleapis.com/auth/firebase.messaging', aud: 'https://oauth2.googleapis.com/token', exp: Math.floor(Date.now() / 1000) + 3600, // 有效期1小时 iat: Math.floor(Date.now() / 1000) }; // 用服务账号私钥签名JWT const signedJwt = jwt.sign(payload, serviceAccount.private_key, { algorithm: 'RS256' }); // 请求Google OAuth端点获取令牌 const response = await axios.post('https://oauth2.googleapis.com/token', null, { params: { grant_type: 'urn:ietf:params:oauth:grant-type:jwt-bearer', assertion: signedJwt } }); return response.data.access_token; }
二、实现Web推送通知的完整流程
1. React前端获取设备注册令牌
先在React项目中集成Firebase SDK,请求通知权限并获取设备的FCM注册令牌,然后将令牌发送到后端存储:
// React组件代码 import { getMessaging, getToken } from "firebase/messaging"; import { initializeApp } from "firebase/app"; // 你的Firebase项目配置 const firebaseConfig = { apiKey: "YOUR_API_KEY", authDomain: "YOUR_AUTH_DOMAIN", projectId: "YOUR_PROJECT_ID", storageBucket: "YOUR_STORAGE_BUCKET", messagingSenderId: "YOUR_SENDER_ID", appId: "YOUR_APP_ID" }; const app = initializeApp(firebaseConfig); const messaging = getMessaging(app); // 请求通知权限并获取注册令牌 async function requestNotificationPermission() { const permission = await Notification.requestPermission(); if (permission === 'granted') { // VAPID密钥在Firebase控制台→云消息传递→Web配置中生成 const token = await getToken(messaging, { vapidKey: 'YOUR_VAPID_KEY' }); // 将令牌发送到后端保存(比如调用后端接口存入数据库) await fetch('/api/save-fcm-token', { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify({ token }) }); } } // 组件挂载时调用 useEffect(() => { requestNotificationPermission(); }, []);
2. 后端调用FCM HTTP v1 API发送通知
后端通过前面的函数获取OAuth令牌,然后调用FCM API发送通知:
async function sendPushNotification(targetToken, title, content) { const accessToken = await getAccessToken(); const projectId = 'YOUR_FIREBASE_PROJECT_ID'; const notificationPayload = { message: { token: targetToken, notification: { title: title, body: content }, webpush: { notification: { icon: '/path/to/your-app-icon.png', // 可选:通知图标 click_action: 'https://your-app-domain.com' // 可选:点击通知跳转的URL } } } }; await axios.post( `https://fcm.googleapis.com/v1/projects/${projectId}/messages:send`, notificationPayload, { headers: { 'Authorization': `Bearer ${accessToken}`, 'Content-Type': 'application/json' } } ); } // 示例:触发通知的后端接口 app.post('/api/send-notification', async (req, res) => { const { token, title, content } = req.body; try { await sendPushNotification(token, title, content); res.status(200).json({ success: true }); } catch (err) { res.status(500).json({ success: false, error: err.message }); } });
三、是否需要单独创建生成OAuth令牌的API?
不需要。原因如下:
- OAuth令牌是敏感凭证,一旦暴露给前端会导致安全风险,必须在后端闭环使用
- 用Firebase Admin SDK时,令牌会自动缓存并刷新,无需单独管理
- 前端只需要触发“发送通知”的后端接口即可,无需接触令牌生成逻辑
内容的提问来源于stack exchange,提问作者Rocko V
相关产品推荐
相关产品推荐

