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

Manifest V3下如何修改重定向请求Cookie并实现Cookie沙箱?

Chrome扩展实现Cookie沙箱(替代webRequestBlocking)

针对302重定向场景下异步更新规则失效的问题,以下是两种可行的实现方案:

方案一:预生成标签专属的declarativeNetRequest规则

核心思路是提前为每个标签页创建Cookie隔离规则,避免请求时异步更新规则的竞态问题——302重定向属于同标签请求,会自动匹配预先生成的规则。

  • 步骤1:标签初始化时生成隔离标识
    监听tabs.onCreated事件,为每个新标签初始化专属Cookie存储,并预创建匹配该标签的网络规则:

    chrome.tabs.onCreated.addListener(async (tab) => {
      // 初始化标签专属Cookie存储
      await chrome.storage.session.set({
        [`tab_${tab.id}_cookies`]: {}
      });
      // 预创建该标签的Cookie替换规则
      await chrome.declarativeNetRequest.updateSessionRules({
        addRules: [
          // 拦截请求,替换Cookie头为标签专属值
          {
            id: tab.id + 1000,
            priority: 1,
            action: {
              type: "modifyHeaders",
              requestHeaders: [
                {
                  header: "cookie",
                  operation: "set",
                  value: await getTabCookieString(tab.id)
                }
              ]
            },
            condition: {
              tabIds: [tab.id],
              urlFilter: "*://*/*", // 可缩小到目标站点
              resourceTypes: ["main_frame", "sub_frame", "xmlhttprequest", "script"]
            }
          },
          // 拦截响应,阻止浏览器写入全局Cookie
          {
            id: tab.id + 2000,
            priority: 1,
            action: {
              type: "modifyHeaders",
              responseHeaders: [
                {
                  header: "set-cookie",
                  operation: "remove"
                }
              ]
            },
            condition: {
              tabIds: [tab.id],
              urlFilter: "*://*/*",
              resourceTypes: ["main_frame", "sub_frame", "xmlhttprequest", "script"]
            }
          }
        ]
      });
    });
    
  • 步骤2:处理响应中的Set-Cookie
    用非阻塞的webRequest.onHeadersReceived监听响应,解析Set-Cookie并存入对应标签的存储:

    chrome.webRequest.onHeadersReceived.addListener(
      async (details) => {
        const setCookieHeaders = details.responseHeaders?.filter(h => h.name.toLowerCase() === "set-cookie");
        if (!setCookieHeaders || !details.tabId) return;
        
        const tabCookieKey = `tab_${details.tabId}_cookies`;
        const stored = await chrome.storage.session.get(tabCookieKey);
        const tabCookies = stored[tabCookieKey] || {};
    
        setCookieHeaders.forEach(header => {
          const [keyValue] = header.value.split(";");
          const [key, value] = keyValue.split("=");
          tabCookies[key] = value;
        });
        await chrome.storage.session.set({ [tabCookieKey]: tabCookies });
        // 更新对应标签的请求规则
        await updateTabCookieRule(details.tabId);
      },
      { urls: ["*://*/*"] },
      ["responseHeaders"]
    );
    
  • 步骤3:动态更新请求Cookie规则
    当标签Cookie变化时,更新对应的会话规则:

    async function getTabCookieString(tabId) {
      const tabCookieKey = `tab_${tabId}_cookies`;
      const stored = await chrome.storage.session.get(tabCookieKey);
      return Object.entries(stored[tabCookieKey] || {})
        .map(([k, v]) => `${k}=${v}`)
        .join("; ");
    }
    
    async function updateTabCookieRule(tabId) {
      const cookieStr = await getTabCookieString(tabId);
      await chrome.declarativeNetRequest.updateSessionRules({
        removeRuleIds: [tabId + 1000],
        addRules: [
          {
            id: tabId + 1000,
            priority: 1,
            action: {
              type: "modifyHeaders",
              requestHeaders: [{ header: "cookie", operation: "set", value: cookieStr }]
            },
            condition: { tabIds: [tabId], urlFilter: "*://*/*", resourceTypes: ["main_frame", "sub_frame", "xmlhttprequest", "script"] }
          }
        ]
      });
    }
    

方案二:内容脚本劫持页面Cookie操作

绕开网络层面的竞态,直接在页面上下文重写document.cookie,让页面读写的是扩展存储的标签专属Cookie,同时配合网络拦截确保一致性。

  • 步骤1:配置内容脚本(manifest.json)

    "content_scripts": [
      {
        "matches": ["*://*/*"],
        "js": ["content.js"],
        "runAt": "document_start", // 页面加载前注入,确保优先执行
        "all_frames": true
      }
    ]
    
  • 步骤2:内容脚本重写document.cookie

    // content.js
    (function() {
      chrome.runtime.sendMessage({ action: "getTabId" }, async (tabId) => {
        const tabCookieKey = `tab_${tabId}_cookies`;
        let stored = await chrome.storage.session.get(tabCookieKey);
        let tabCookies = stored[tabCookieKey] || {};
    
        // 重写Cookie读写逻辑
        Object.defineProperty(document, "cookie", {
          get: function() {
            return Object.entries(tabCookies)
              .map(([k, v]) => `${k}=${v}`)
              .join("; ");
          },
          set: function(value) {
            const [keyValue] = value.split(";");
            const [key, val] = keyValue.split("=");
            tabCookies[key] = val;
            chrome.storage.session.set({ [tabCookieKey]: tabCookies });
            // 通知后台更新网络规则
            chrome.runtime.sendMessage({ action: "updateCookieRule", tabId });
            return value;
          },
          configurable: true
        });
      });
    })();
    
  • 步骤3:后台配合处理网络请求
    同方案一的网络拦截逻辑,确保请求头携带标签专属Cookie,响应的Set-Cookie不写入全局存储。

关键注意事项

  • 用chrome.storage.session存储标签专属Cookie,标签关闭后自动清除,避免内存泄漏。
  • 缩小declarativeNetRequest的urlFilter范围,只匹配目标站点,提升性能。
  • 需处理Cookie的domain、path、expires等属性,确保隔离规则符合Cookie规范。
  • 覆盖所有相关资源类型(如xmlhttprequest、script),避免遗漏跨域请求的Cookie处理。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.03 11:47:09