Safari Web Extension如何发送带认证Cookie的请求?
最可靠的解决办法:用后台脚本代理请求
Safari在内容脚本/弹出页里直接用Fetch时,对SameSite=Strict的HttpOnly Cookie处理逻辑和Chrome、Firefox不一样,而后台脚本的上下文不受扩展域名随机化的影响,能正常利用配置的权限携带Cookie。
步骤1:确认manifest权限配置
确保manifest.json里的权限配全,还要加上HTTPS前缀(匹配Cookie的Secure属性):
{ "host_permissions": ["https://mydomain.com/*"], "permissions": ["cookies"], "background": { "service_worker": "background.js" } }
步骤2:后台脚本实现请求代理
在background.js里加消息监听,处理扩展其他部分发来的请求:
browser.runtime.onMessage.addListener(async (req, sender, sendRes) => { if (req.action === "fetchWithCookie") { try { const res = await fetch(req.url, { method: req.method || "GET", headers: req.headers || {}, body: req.body, credentials: "include" // 关键:自动带上目标域名的Cookie }); const data = await res.json(); // 按需调整响应格式,比如text() sendRes({ success: true, data, status: res.status }); } catch (err) { sendRes({ success: false, error: err.message }); } return true; // 告诉浏览器要异步返回响应 } });
步骤3:在扩展其他上下文调用代理
比如内容脚本或弹出页里,通过消息把请求发给后台:
async function fetchWithAuth(url, options = {}) { const res = await browser.runtime.sendMessage({ action: "fetchWithCookie", url, method: options.method, headers: options.headers, body: options.body }); if (res.success) { return res.data; } else { throw new Error(res.error); } } // 使用示例 fetchWithAuth("https://mydomain.com/api/user") .then(console.log) .catch(console.error);
为啥直接Fetch不行?
- Safari对扩展的上下文隔离更严,内容脚本/弹出页的域名被随机化后,就算有host_permissions,SameSite=Strict的Cookie也不会自动带到跨域请求里——Strict模式要求请求发起方和Cookie域名完全一致,扩展的随机域名显然不满足。
- WebSocket能正常带Cookie是因为Safari对它的处理逻辑和Fetch不一样,在有权限的情况下,WebSocket的Cookie携带不受SameSite=Strict的跨域限制。
额外注意点
- 目标域名的Cookie必须是Secure的,而且请求必须走HTTPS,Safari不会在HTTP请求里带Secure Cookie。
- 不用关「阻止跨域追踪」,后台代理的请求是从扩展后台发起的,不属于跨域追踪的范畴,能绕过这个限制。
- 如果要传FormData、Blob这类复杂数据,得注意消息传递时的序列化问题,或者用
browser.runtime.connect建立长连接来传二进制数据。
内容的提问来源于stack exchange,提问作者Dalzhim
相关产品推荐
相关产品推荐

