Chrome Manifest V3中Cookie实现背景与内容脚本通信的问题
问题根源
你用declarativeNetRequest全局设置Cookie的方式会干扰网站自身Cookie机制(比如CSRF令牌、会话Cookie):operation: "set"可能覆盖同名Cookie,或者自定义Cookie的属性(如SameSite、Secure)不符合网站的安全策略,导致登录验证失败、重定向循环等异常。
替代方案
方案1:用chrome.storage.session同步UA(document_start读取)
利用MV3新增的会话级存储,内容脚本在页面最早期读取UA,无需依赖网络请求的Cookie。
背景脚本设置UA:
// 背景脚本中更新自定义UA到会话存储 chrome.storage.session.set({ customUserAgent: encodeURIComponent(agent) });
内容脚本(manifest配置run_at: "document_start"):
// 页面启动时立即读取UA并修改navigator chrome.storage.session.get("customUserAgent").then(result => { const targetUA = result.customUserAgent ? decodeURIComponent(result.customUserAgent) : null; if (!targetUA) return; // 覆盖核心UA属性 Object.defineProperty(navigator, 'userAgent', { get: () => targetUA, configurable: true, enumerable: true }); // 可选:同步覆盖其他关联属性(按需调整) const uaParts = targetUA.split(' '); Object.defineProperty(navigator, 'appVersion', { get: () => uaParts.find(part => part.startsWith('AppleWebKit/')) || navigator.appVersion, configurable: true, enumerable: true }); Object.defineProperty(navigator, 'platform', { get: () => uaParts.find(part => part.startsWith('Windows') || part.startsWith('Macintosh')) || navigator.platform, configurable: true, enumerable: true }); // 处理现代浏览器的userAgentData if (navigator.userAgentData) { Object.defineProperty(navigator, 'userAgentData', { get: () => ({ brands: [ { brand: 'Not/A)Brand', version: '99' }, { brand: 'Google Chrome', version: uaParts.find(part => part.startsWith('Chrome/')).split('/')[1] }, { brand: 'Chromium', version: uaParts.find(part => part.startsWith('Chrome/')).split('/')[1] } ], platform: targetUA.includes('Windows') ? 'Windows' : targetUA.includes('Mac') ? 'macOS' : navigator.userAgentData.platform, mobile: targetUA.includes('Mobile'), getHighEntropyValues: async (hints) => { // 按需返回高熵值,模拟真实浏览器 const base = await navigator.userAgentData.getHighEntropyValues(hints); return { ...base, platformVersion: targetUA.includes('Windows NT 10.0') ? '10.0' : base.platformVersion }; } }), configurable: true }); } });
方案2:背景脚本直接注入UA修改代码(精准时机控制)
通过chrome.scripting.executeScript在document_start阶段直接注入携带UA的脚本,完全跳过存储/通信环节,时机最精准。
背景脚本代码:
// 监听页面导航,主框架加载前注入脚本 chrome.webNavigation.onBeforeNavigate.addListener(async (details) => { // 仅处理主框架、HTTP/HTTPS页面 if (details.frameId !== 0 || !details.url.startsWith('http')) return; const targetUA = /* 你的自定义UA字符串 */; try { await chrome.scripting.executeScript({ target: { tabId: details.tabId }, world: 'MAIN', // 必须用MAIN世界才能修改页面全局的navigator runAt: 'document_start', func: (customUA) => { // 核心UA覆盖 Object.defineProperty(navigator, 'userAgent', { get: () => customUA, configurable: true, enumerable: true }); // 关联属性覆盖(按需调整) Object.defineProperty(navigator, 'appVersion', { get: () => customUA.split(' ').find(p => p.startsWith('AppleWebKit/')) || navigator.appVersion, configurable: true, enumerable: true }); // userAgentData处理 if (navigator.userAgentData) { const chromeVersion = customUA.split(' ').find(p => p.startsWith('Chrome/')).split('/')[1]; Object.defineProperty(navigator, 'userAgentData', { get: () => ({ brands: [ { brand: 'Not/A)Brand', version: '99' }, { brand: 'Google Chrome', version: chromeVersion }, { brand: 'Chromium', version: chromeVersion } ], platform: customUA.includes('Windows') ? 'Windows' : 'macOS', mobile: customUA.includes('Mobile'), getHighEntropyValues: async (hints) => { const res = {}; if (hints.includes('platformVersion')) { res.platformVersion = customUA.includes('Windows NT 10.0') ? '10.0' : '13.4.1'; } return res; } }), configurable: true }); } }, args: [targetUA] }); } catch (err) { console.error('注入UA修改脚本失败:', err); } });
关键注意事项
- 必须用
document_start:确保在页面任何脚本执行前完成UA修改,才能通过webbrowsertools的严格测试。 - 覆盖所有UA相关属性:现代浏览器会通过
navigator.userAgent、userAgentData等多个属性获取UA信息,仅修改一个可能被检测到。 - 避免全局Cookie操作:不要用
declarativeNetRequest修改或添加Cookie,这几乎必然会干扰网站自身的会话和安全验证机制。
内容的提问来源于stack exchange,提问作者Escape75
相关产品推荐
相关产品推荐

