如何让 JavaScript fetch 使用与浏览器当前状态不同的 Cookie?
结论
普通网页 JavaScript 无法让浏览器原生 fetch() 在某一次请求中使用任意指定的 Cookie 集合。题目中的例子不能直接要求它只发送 key2=anothervalue2,同时排除浏览器已有的 key1=value1。
如果可以使用用户脚本,可以尝试 Tampermonkey 的特权请求 API。能否实现所需的组合,取决于脚本管理器和浏览器环境。
为什么 fetch 不能直接替换 Cookie
浏览器根据 Cookie 存储和匹配规则生成请求的 Cookie 请求头。Cookie 是禁止网页脚本设置的请求头,即使请求目标与当前页面同源,也不能通过 headers 指定。参见 Fetch Standard。
下面的写法无法达到目的:
// 无效方案:网页 fetch 不能自行设置 Cookie 请求头。
fetch('/page', {
credentials: 'omit',
headers: {
Cookie: 'key2=anothervalue2'
}
});
credentials 控制凭据的携带策略,不能逐个筛选或替换 Cookie:
omit:不携带浏览器 Cookie,也不接受响应中的Set-Cookie。same-origin:默认值,仅在同源请求中携带凭据。include:允许跨源请求携带凭据,但仍受 Cookie 匹配规则和浏览器策略限制。
如果只需要完全不带 Cookie,可以使用下面的写法;它不能满足“仅发送自定义 Cookie”的需求。参见 Request.credentials 文档。
const response = await fetch('/page', {
credentials: 'omit'
});
const html = await response.text();
用户脚本可以尝试什么方案
Tampermonkey 的 GM_xmlhttpRequest 提供 anonymous 和 cookie 参数。文档说明,anonymous 不发送 Cookie,cookie 则合并指定 Cookie 并替换同名 Cookie。因此,单独设置 cookie 不能保证排除已有的 key1。参见 Tampermonkey 请求 API 文档。
如果所用实现支持禁用已有 Cookie,同时注入显式指定的 Cookie,可以尝试以下组合。使用时请将示例域名和路径替换为实际目标:
// ==UserScript==
// @name Fetch with custom cookies
// @match https://example.com/*
// @grant GM_xmlhttpRequest
// @connect example.com
// ==/UserScript==
GM_xmlhttpRequest({
method: 'GET',
url: 'https://example.com/page',
anonymous: true,
cookie: 'key2=anothervalue2',
onload(response) {
console.log(response.status);
console.log(response.responseText);
},
onerror(error) {
console.error('Request failed', error);
}
});
这段代码需要由 Tampermonkey 执行,普通网页控制台不提供该 API,也不能直接把它当作 Greasemonkey 或其他管理器的通用写法。
文档对这两个参数组合后的行为说明有限。使用时,应通过受控服务端日志或请求回显接口确认最终收到的 Cookie 是否只有 key2=anothervalue2,以及是否仍包含 key1。页面返回正常,并不能证明 Cookie 已按预期替换;也不要把真实登录 Cookie 发给公共回显服务。
为什么备份、删除、恢复不可靠
HttpOnly 限制网页 JavaScript 读取和修改 Cookie,但这些 Cookie 仍可随符合条件的 fetch() 请求发送。因此,document.cookie 无法完整备份、删除和恢复它们。参见 HttpOnly 属性说明。
即使只涉及普通 Cookie,这种办法也会改变共享的 Cookie 存储。其他标签页或并发请求可能在删除与恢复之间发出请求。同名 Cookie 也可能具有不同的 Domain、Path 和有效期,仅保存名称和值不足以完整恢复状态。
需要严格隔离时如何处理
如果用户脚本环境无法可靠实现该需求,可以将请求移到自己控制的后端,由后端 HTTP 客户端显式设置 Cookie: key2=anothervalue2,并避免附带其他会话的 Cookie。浏览器传给后端的 Cookie 不应自动透传给目标网站。
也可以使用独立浏览器配置文件或独立自动化上下文,建立单独的 Cookie 存储后再请求目标页面。这适合需要维持另一套会话的场景,但仍需自行设置所需 Cookie。
备注:内容仅供参考。
