如何在浏览器扩展内容脚本中添加不安全请求头?兼容MV2/MV3
在浏览器扩展中发送含不安全请求头的AJAX请求(兼容Manifest V2/V3)
核心思路:内容脚本直接发起请求会受页面安全策略限制,无法设置Sec-Fetch-Mode这类浏览器标记的"不安全头"。必须借助扩展的后台脚本(Manifest V2)或Service Worker(Manifest V3)来发送请求——这类扩展上下文不受页面安全限制,只要配置对应权限就能自由设置请求头。内容脚本通过消息通信的方式将请求参数传递给后台,由后台完成请求后返回响应。
Manifest V2 实现步骤
1. 配置manifest.json
添加目标域名权限、后台脚本和内容脚本声明:
{ "manifest_version": 2, "name": "OpenProject 请求工具", "version": "1.0", "permissions": [ "https://你的OpenProject域名/*", "activeTab" ], "background": { "scripts": ["background.js"] }, "content_scripts": [ { "matches": ["https://你的OpenProject域名/*"], "js": ["content.js"] } ] }
2. 内容脚本(content.js)
封装消息发送逻辑,将请求参数传给后台:
// 封装请求函数 function sendSecureRequest(url, options) { return new Promise((resolve, reject) => { chrome.runtime.sendMessage({ action: "sendAjax", url: url, method: options.method || "GET", headers: options.headers, body: options.body }, (response) => { if (chrome.runtime.lastError) { reject(chrome.runtime.lastError); } else { resolve(response); } }); }); } // 使用示例 sendSecureRequest("https://你的OpenProject域名/api/v3/work_packages", { method: "GET", headers: { "Sec-Fetch-Mode": "cors", "Sec-Fetch-Dest": "empty", "Content-Type": "application/json" } }).then(res => console.log(res)).catch(err => console.error(err));
3. 后台脚本(background.js)
监听消息,发起请求并返回响应:
chrome.runtime.onMessage.addListener((request, sender, sendResponse) => { if (request.action === "sendAjax") { const { url, method, headers, body } = request; fetch(url, { method: method, headers: new Headers(headers), body: body ? JSON.stringify(body) : null, credentials: "include" // 携带登录Cookie,和页面请求保持一致 }) .then(res => res.json()) .then(data => sendResponse(data)) .catch(err => sendResponse({ error: err.message })); // 返回true保持消息通道开放,等待异步请求完成 return true; } });
Manifest V3 实现步骤
V3与V2核心逻辑一致,仅manifest配置和后台载体不同(Service Worker替代传统后台脚本)。
1. 配置manifest.json
注意host_permissions和service_worker的声明:
{ "manifest_version": 3, "name": "OpenProject 请求工具", "version": "1.0", "permissions": ["activeTab"], "host_permissions": [ "https://你的OpenProject域名/*" ], "background": { "service_worker": "background.js" }, "content_scripts": [ { "matches": ["https://你的OpenProject域名/*"], "js": ["content.js"] } ] }
2. 内容脚本(content.js)
与V2完全一致,无需修改。
3. Service Worker 脚本(background.js)
逻辑和V2后台脚本一致,仅运行环境为Service Worker:
chrome.runtime.onMessage.addListener((request, sender, sendResponse) => { if (request.action === "sendAjax") { const { url, method, headers, body } = request; fetch(url, { method: method, headers: new Headers(headers), body: body ? JSON.stringify(body) : null, credentials: "include" }) .then(res => res.json()) .then(data => sendResponse(data)) .catch(err => sendResponse({ error: err.message })); return true; } });
关键注意事项
- 权限必须配置:无论V2还是V3,都需要在manifest中声明目标域名的访问权限,否则后台无法发起请求。
- 凭证携带:如果需要保持用户登录状态,务必添加
credentials: "include",确保请求携带目标域名的Cookie。 - 灵活性:这种方式支持动态设置任意请求头,比
declarativeNetRequest(V3批量修改头的方案)更适合按需定制请求的场景。
内容的提问来源于stack exchange,提问作者Eric Roy
相关产品推荐
相关产品推荐

