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

如何为与MV3 Chrome扩展交互的Firebase后端做安全防护(含AppCheck、Auth)

Chrome扩展对接Firebase时的恶意请求防护方案

一、绕过Manifest V3 CSP限制,实现AppCheck验证

由于reCAPTCHA需要加载外部脚本,完全不符合Manifest V3的内容安全策略(CSP),这里可以改用自定义AppCheck提供者,利用Chrome扩展的唯一标识(扩展ID)和用户认证信息生成验证令牌:

  • 扩展端实现:
    在扩展的弹窗或后台脚本中,生成包含扩展ID、用户UID(来自Firebase Auth)的自定义JWT令牌(注意MV3中要使用ES模块版本的JWT库,比如jwt-esm):

    // 扩展端代码(后台/弹窗)
    import jwt from 'jwt-esm';
    const generateAppCheckToken = async (user) => {
      const payload = {
        iss: chrome.runtime.id, // 你的扩展唯一ID
        sub: user.uid, // 当前登录用户的UID
        exp: Math.floor(Date.now() / 1000) + 3600 // 令牌有效期设为1小时
      };
      // 用你自己生成的密钥签名,注意密钥要保密,别打包到扩展里
      return jwt.sign(payload, 'YOUR_CUSTOM_APPCHECK_SECRET', { algorithm: 'HS256' });
    };
    

    调用Callable函数时,把这个自定义令牌作为参数传递给云端,或者用自定义HTTP头传递(如果改用HTTP触发器的话)。

  • Cloud Functions端验证:
    在Cloud Functions中配置AppCheck的自定义验证逻辑,校验令牌的合法性:

    // Cloud Functions端代码
    const { initializeAppCheck, CustomProvider } = require('firebase-admin/app-check');
    const jwt = require('jsonwebtoken');
    
    initializeAppCheck(app, {
      provider: new CustomProvider({
        getToken: async (request) => {
          // 从Callable请求的参数里拿到自定义令牌
          const appCheckToken = request.rawRequest.body.data.appCheckToken;
          try {
            // 验证签名和内容
            const decoded = jwt.verify(appCheckToken, 'YOUR_CUSTOM_APPCHECK_SECRET');
            // 校验扩展ID是否和你的官方扩展一致
            if (decoded.iss !== 'YOUR_OFFICIAL_EXTENSION_ID') {
              throw new Error('非法扩展来源');
            }
            return { token: appCheckToken, valid: true };
          } catch (err) {
            return { token: appCheckToken, valid: false };
          }
        }
      }),
      isTokenAutoRefreshEnabled: false
    });
    

    这样既避开了MV3的CSP限制,又能确保请求来自你的合法扩展。

二、提前拦截未认证/非法请求,减少函数触发次数

1. 扩展端前置拦截

在调用云端函数前,先强制检查用户是否已登录,未登录直接阻断请求,根本不往云端发:

// 扩展端代码
const callProtectedFunction = async () => {
  const user = firebase.auth().currentUser;
  if (!user) {
    alert('请先登录账号');
    return;
  }
  // 生成自定义AppCheck令牌
  const appCheckToken = await generateAppCheckToken(user);
  // 调用Callable函数
  const result = await firebase.functions().httpsCallable('yourTargetFunction')({
    // 业务参数
    appCheckToken: appCheckToken
  });
};

2. Cloud Functions端快速拦截

在Callable函数的最开头,先检查用户认证状态和AppCheck令牌,不合法直接抛出错误,避免执行后续业务逻辑:

// Cloud Functions端Callable函数
exports.yourTargetFunction = functions.https.onCall(async (data, context) => {
  // 第一步:检查用户是否已认证
  if (!context.auth) {
    throw new functions.https.HttpsError('unauthenticated', '用户未登录');
  }
  // 第二步:验证自定义AppCheck令牌
  const appCheckToken = data.appCheckToken;
  try {
    const decoded = jwt.verify(appCheckToken, 'YOUR_CUSTOM_APPCHECK_SECRET');
    // 确保令牌中的用户UID和当前认证用户一致,且来源是你的扩展
    if (decoded.iss !== 'YOUR_OFFICIAL_EXTENSION_ID' || decoded.sub !== context.auth.uid) {
      throw new Error('非法请求');
    }
  } catch (err) {
    throw new functions.https.HttpsError('failed-precondition', '请求不合法');
  }
  // 第三步:执行正常业务逻辑
  // ...
});

3. 改用HTTP触发器替代Callable函数

如果需要更前置的拦截(比如连函数初始化都不想触发),可以改用HTTP触发器,在请求到达时直接验证ID Token和AppCheck令牌,不合法就返回401:

// Cloud Functions端HTTP触发器
exports.yourHttpFunction = functions.https.onRequest(async (req, res) => {
  // 从请求头获取Firebase Auth的ID Token
  const idToken = req.headers.authorization?.split('Bearer ')[1];
  if (!idToken) {
    return res.status(401).send('缺少身份令牌');
  }
  try {
    // 验证ID Token
    const decodedToken = await admin.auth().verifyIdToken(idToken);
    // 获取自定义AppCheck令牌
    const appCheckToken = req.headers['x-appcheck-token'];
    const decodedAppCheck = jwt.verify(appCheckToken, 'YOUR_CUSTOM_APPCHECK_SECRET');
    // 校验扩展ID和用户UID匹配
    if (decodedAppCheck.iss !== 'YOUR_OFFICIAL_EXTENSION_ID' || decodedAppCheck.sub !== decodedToken.uid) {
      return res.status(403).send('请求非法');
    }
    // 执行业务逻辑
    res.status(200).send('请求成功');
  } catch (err) {
    return res.status(401).send('令牌验证失败');
  }
});

三、额外防护措施,降低计费风险

  • 设置Cloud Functions配额:在Google Cloud控制台给每个函数设置每日调用次数、CPU使用时长的限额,超过后自动拒绝请求。
  • 启用Firebase计费告警:设置账单阈值,当费用接近阈值时触发邮件提醒,及时发现异常流量。
  • 绑定API密钥到扩展ID:在Google Cloud控制台的API密钥管理中,将你的Firebase API密钥限制为仅允许你的Chrome扩展ID使用,防止第三方盗用密钥调用API。
  • 启用VPC服务控制:将Cloud Functions加入VPC服务边界,限制只能从合法来源访问。

内容的提问来源于stack exchange,提问作者luigisuncorner

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.26 00:54:54