Chrome扩展如何在后台/内容脚本中监听含响应体的全页面网络流量
该需求可以实现,并非完全受安全限制无法完成,目前有两种常用的落地方案,分别适用于不同场景:
方案1:内容脚本Hook原生XMLHttpRequest和fetch
该方案无需特殊权限,无任何弹窗提示,Manifest V2和V3版本的扩展都支持,适合绝大多数场景使用。
实现逻辑是在页面上下文注入自定义脚本,重写浏览器原生的XMLHttpRequest和fetch方法,在请求收到响应后直接读取完整响应体,再通过跨上下文消息传递把数据传给内容脚本,最终转发给后台脚本即可。
注入到页面上下文的Hook代码
// 重写fetch方法 const originalFetch = window.fetch; window.fetch = function(...args) { return originalFetch.apply(this, args) .then(async (response) => { // 克隆响应对象,避免影响原请求的正常流转 const clonedRes = response.clone(); try { const responseBody = await clonedRes.text(); // 发送自定义事件传递给内容脚本 window.postMessage({ type: 'NETWORK_RESPONSE', url: response.url, status: response.status, body: responseBody }, '*'); } catch (err) {} return response; }); }; // 重写XMLHttpRequest方法 const originalXhrOpen = XMLHttpRequest.prototype.open; XMLHttpRequest.prototype.open = function(...args) { this.addEventListener('load', () => { try { window.postMessage({ type: 'NETWORK_RESPONSE', url: args[1], status: this.status, body: this.responseText }, '*'); } catch (err) {} }); return originalXhrOpen.apply(this, args); };
内容脚本监听代码
window.addEventListener('message', (event) => { if (event.data?.type === 'NETWORK_RESPONSE') { // 可通过runtime.sendMessage把数据传给background.js chrome.runtime.sendMessage(event.data); } });
- 优点:无弹窗、不需要额外高风险权限、实现简单
- 缺点:如果页面本身有反Hook逻辑可能被拦截,无法直接获取WebSocket流量
方案2:使用chrome.debugger API
该方案适合需要获取全量网络流量、避免被页面反Hook检测的场景。你之前提到的调试提示弹窗是旧版本Chrome的限制,现在只要在manifest.json中提前声明debugger权限,用户安装扩展时统一授权后,后续调用不会再弹出顶部的调试提示条。
manifest.json配置(Manifest V3)
{ "manifest_version": 3, "name": "流量监听扩展", "version": "1.0", "permissions": ["debugger", "tabs"], "background": { "service_worker": "background.js" } }
background.js代码
// 监听标签页加载完成事件,自动挂载调试器 chrome.tabs.onUpdated.addListener(async (tabId, changeInfo, tab) => { if (changeInfo.status === 'complete' && tab.url?.startsWith('http')) { try { // 挂载调试器,使用1.3版本协议 await chrome.debugger.attach({tabId}, '1.3'); // 启用网络域监听 await chrome.debugger.sendCommand({tabId}, 'Network.enable'); // 监听响应接收事件 chrome.debugger.onEvent.addListener(async (debuggeeId, method, params) => { if (debuggeeId.tabId !== tabId) return; if (method === 'Network.responseReceived') { // 调用接口获取响应体 const responseData = await chrome.debugger.sendCommand( {tabId}, 'Network.getResponseBody', {requestId: params.requestId} ); console.log('请求地址:', params.response.url); console.log('响应体:', responseData.body); } }); } catch (err) { console.error('调试器挂载失败:', err); } } }); // 标签页关闭时卸载调试器 chrome.tabs.onRemoved.addListener((tabId) => { chrome.debugger.detach({tabId}).catch(() => {}); });
- 优点:不会被页面反Hook逻辑检测、支持获取所有类型的网络流量(含WebSocket)
- 缺点:需要申请debugger权限,Chrome内置页面、高权限敏感页面(如银行支付页)无法挂载调试器
内容的提问来源于stack exchange,提问作者ibrahimAKIN
相关产品推荐
相关产品推荐

