如何将使用chrome.webRequest的代理代码适配为支持Manifest V3?
适配Manifest V3的代理设置与认证改造方案
原代码依赖的chrome.webRequest在Manifest V3(以下简称MV3)中受限:blocking类型的监听仅允许在**后台服务工作者(Service Worker)**中使用,且官方推荐用chrome.declarativeNetRequest替代大部分请求拦截逻辑。以下是针对代理设置和认证逻辑的改造步骤:
1. 配置Manifest必要权限
先在manifest.json中添加所需权限,确保功能正常运行:
{ "permissions": [ "proxy", "declarativeNetRequest", "<all_urls>" // 可按需缩小主机范围 ], "background": { "service_worker": "background.js" } }
2. 重构核心逻辑
原代码的两种认证场景(被动响应弹窗、主动注入认证头),在MV3中可通过以下方式替代:
方案一:主动注入Proxy-Authorization请求头(推荐)
对应原代码onBeforeSendHeaders的逻辑,用declarativeNetRequest添加声明式规则,直接在请求头中注入代理认证信息,无需等待浏览器触发认证弹窗:
Proxy.prototype.setProxy = function(proxyAddress, proxyUsername, proxyPassword) { // 清除旧的认证规则,避免重复注入 const clearAuthRules = async () => { await chrome.declarativeNetRequest.updateDynamicRules({ removeRuleIds: [1] // 规则ID需保持唯一,可按需调整 }); }; if (!proxyAddress || proxyAddress.trim() === "") { setProxySettings(config()) .then(clearAuthRules) .then(debugProxySettings) .catch(error => console.error("Error setting proxy:", error)); } else { setProxySettings(config(proxyAddress)) .then(async () => { if (proxyAddress.trim() && proxyUsername.trim()) { // 生成Base64编码的代理凭证 const authToken = btoa(`${proxyUsername.trim()}:${proxyPassword.trim()}`); // 添加动态规则注入认证头 await chrome.declarativeNetRequest.updateDynamicRules({ addRules: [ { id: 1, priority: 1, action: { type: "modifyHeaders", requestHeaders: [ { operation: "set", header: "Proxy-Authorization", value: `Basic ${authToken}` } ] }, condition: { urlFilter: "*", resourceTypes: ["main_frame", "sub_frame", "stylesheet", "script", "image", "font", "xmlhttprequest", "media", "websocket", "other"] } } ] }); } else { await clearAuthRules(); } debugProxySettings(proxyUsername, proxyPassword); }) .catch(error => console.error("Error setting proxy:", error)); } };
方案二:被动响应代理认证挑战(仅Service Worker可用)
若需保留类似原代码onAuthRequired的被动响应逻辑,MV3中仅允许在Service Worker中使用chrome.webRequest.onAuthRequired的blocking监听,需额外添加webRequest和webRequestBlocking权限:
// 此代码必须放在Service Worker文件(如background.js)中 chrome.webRequest.onAuthRequired.addListener( details => { return { authCredentials: { username: proxyUsername.trim(), // 需确保变量在Service Worker上下文可访问 password: proxyPassword.trim() } }; }, { urls: ["<all_urls>"] }, ["blocking"] );
注意:此方式性能低于主动注入请求头,且受限于Service Worker上下文,官方更推荐方案一。
3. 关键注意事项
- 动态规则ID需全局唯一,更新规则时务必清理旧规则,避免冲突。
- 若用户名/密码包含非ASCII字符,不能直接用
btoa,需先转UTF-8再编码。 - 原
setProxySettings函数需适配MV3环境,chrome.proxy.settings在MV3中仍可使用,但调用需在Service Worker或扩展页面内。
内容的提问来源于stack exchange,提问作者Adhil
相关产品推荐
相关产品推荐

