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

如何基于React实现Manifest V3 Chrome扩展Firebase谷歌账号认证?

分步实现Manifest V3 Chrome扩展 + Firebase登录(内嵌iframe方案)

1. 配置Manifest V3文件

调整manifest.json,确保CSP、权限和页面配置符合Manifest V3规则:

  • 新增必要权限:identity(用于身份验证)、storage(存储用户状态)
  • 配置CSP:允许Firebase资源加载及谷歌登录iframe的访问
  • 注册登录页面并暴露为可访问资源

示例manifest.json核心片段:

{
  "manifest_version": 3,
  "name": "你的扩展名称",
  "version": "1.0",
  "permissions": ["identity", "storage"],
  "action": {
    "default_popup": "index.html" // React打包后的主弹窗页面
  },
  "content_security_policy": {
    "extension_pages": "script-src 'self'; object-src 'none'; frame-src https://accounts.google.com/;",
    "sandbox": "sandbox allow-scripts allow-top-navigation; script-src 'self' https://www.gstatic.com/firebasejs/9.23.0/firebase-app.js https://www.gstatic.com/firebasejs/9.23.0/firebase-auth.js;"
  },
  "web_accessible_resources": [
    {
      "resources": ["login.html"],
      "matches": ["<all_urls>"]
    }
  ]
}

2. 安装并初始化Firebase(React项目)

  • 通过npm安装Firebase模块化SDK:
npm install firebase
  • 创建firebase.config.js初始化Firebase实例:
import { initializeApp } from "firebase/app";
import { getAuth } from "firebase/auth";
import { getFirestore } from "firebase/firestore";

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);
export const auth = getAuth(app);
export const db = getFirestore(app);

3. 构建内嵌登录的React弹窗组件

在主弹窗组件(如Popup.js)中嵌入登录iframe,并监听来自iframe的登录结果:

import { useEffect, useState } from 'react';
import { auth } from './firebase.config';
import { signInWithCredential, GoogleAuthProvider } from 'firebase/auth';

function Popup() {
  const [user, setUser] = useState(null);

  useEffect(() => {
    const handleMessage = (event) => {
      // 验证消息来源为扩展内部
      if (event.origin !== chrome.runtime.getURL('')) return;
      
      if (event.data.type === 'LOGIN_SUCCESS') {
        const credential = GoogleAuthProvider.credential(event.data.idToken);
        signInWithCredential(auth, credential)
          .then(userCredential => setUser(userCredential.user))
          .catch(err => console.error('凭证验证失败:', err));
      }
    };
    window.addEventListener('message', handleMessage);
    return () => window.removeEventListener('message', handleMessage);
  }, []);

  if (user) {
    return <div>已登录:{user.email}</div>;
  }

  return (
    <div style={{ width: '300px', padding: '20px' }}>
      <h3>登录你的账号</h3>
      <iframe
        src={chrome.runtime.getURL('login.html')}
        style={{ width: '100%', height: '400px', border: 'none' }}
        title="Firebase Login"
      ></iframe>
    </div>
  );
}

export default Popup;

4. 编写独立登录页面(login.html)

在React项目public目录下创建login.html,实现谷歌登录逻辑并通过postMessage传递结果:

<!DOCTYPE html>
<html>
<head>
  <meta charset="UTF-8">
  <title>登录</title>
  <script src="https://www.gstatic.com/firebasejs/9.23.0/firebase-app.js"></script>
  <script src="https://www.gstatic.com/firebasejs/9.23.0/firebase-auth.js"></script>
</head>
<body>
  <div id="loginBtn"></div>
  <script>
    const firebaseConfig = {
      // 与React项目中一致的Firebase配置
      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 = firebase.initializeApp(firebaseConfig);
    const auth = firebase.auth();
    const provider = new firebase.auth.GoogleAuthProvider();
    provider.setCustomParameters({ prompt: 'select_account' });

    // 处理登录重定向结果
    auth.getRedirectResult().then(result => {
      if (result.user) {
        result.user.getIdToken().then(idToken => {
          window.parent.postMessage(
            { type: 'LOGIN_SUCCESS', idToken },
            chrome.runtime.getURL('')
          );
        });
      }
    }).catch(err => console.error('登录错误:', err));

    // 渲染登录按钮
    document.getElementById('loginBtn').innerHTML = 
      '<button onclick="auth.signInWithRedirect(provider)">使用谷歌账号登录</button>';
  </script>
</body>
</html>

5. 执行Firestore CRUD操作

登录成功后,即可通过初始化的db对象操作Firestore:

import { collection, addDoc, getDocs } from "firebase/firestore";
import { db } from './firebase.config';

// 添加数据
const addUser = async (user) => {
  try {
    const docRef = await addDoc(collection(db, "users"), {
      email: user.email,
      name: user.displayName
    });
    console.log("文档ID:", docRef.id);
  } catch (e) {
    console.error("添加失败:", e);
  }
};

// 获取数据
const fetchUsers = async () => {
  const querySnapshot = await getDocs(collection(db, "users"));
  querySnapshot.forEach(doc => {
    console.log(`${doc.id} =>`, doc.data());
  });
};

关键注意事项

  • CSP配置必须严格:Manifest V3的extension_pages不允许unsafe-inline/unsafe-eval,需指定具体Firebase CDN版本,避免通配符
  • 消息来源验证:使用postMessage时必须校验event.origin,防止恶意消息注入
  • Firebase控制台配置:需在“授权域”中添加扩展ID(格式:chrome-extension://<你的扩展ID>)

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.22 19:07:07