技术咨询、项目合作、广告投放、简历咨询、技术文档下载 点击这里 联系博主

# 一、CRUD(增删改查)

# 1. 新增 / 修改 (覆盖)

本质上,新增和修改是同一操作。如果指定 keydomainpath 的 Cookie 已存在,则覆盖;否则,创建新的。

// 新增或修改一个有效期为 1 小时的 Cookie
document.cookie = "key=value; domain=example.com; path=/; max-age=3600";

  • 关键原则:同名 + 同 domain + 同 path ⇒ 覆盖。任一属性不一致,则会创建一个全新的 Cookie,导致同名 Cookie 共存。

# 2. 删除

通过将 expires 设为过去的时间点或 max-age 设为 0 或负数来删除 Cookie。

// 删除 Cookie,必须指定确切的 domain 和 path
document.cookie = "key=; domain=example.com; path=/; expires=Thu, 01 Jan 1970 00:00:00 UTC;";

  • 关键原则:删除时必须提供与待删除 Cookie 完全一致的 domainpath,否则无法找到目标 Cookie,导致删除失败。

# 3. 读取

JavaScript 只能读取非 HttpOnly 的 Cookie。

const allCookies = document.cookie; // 返回一个字符串,格式如 "key1=value1; key2=value2"

  • 可见性限制:设置了 HttpOnly 标志的 Cookie 对客户端 JavaScript 脚本是不可见的,无法通过 document.cookie 读取或修改。

# 二、Cookie 操作的核心判断

一个 Cookie 能否被读取或写入,取决于以下几个核心条件的组合。

属性 限制 说明
HttpOnly 无法通过 JS 读/写 该 Cookie 只能由服务器设置,并随 HTTP 请求自动发送,客户端脚本无权访问。
Domain 不匹配 无法读/写 当前页面的域名必须匹配 Cookie 的 domain 属性。例如,a.com 的页面无法操作 domain=b.com 的 Cookie。
Path 不匹配 无法读/写 当前页面的路径必须匹配 Cookie 的 path 属性。例如,/login 页面无法操作 path=/admin 的 Cookie。
Secure + 非 HTTPS 无法写入 如果 Cookie 设置了 Secure 标志,那么它只能在 HTTPS 协议下被创建和发送。在 HTTP 页面上无法写入 Secure Cookie。
  • 一句话总结:要让 JS 能操作 Cookie,必须同时满足:非 HttpOnly + 当前域名匹配 domain + 当前路径匹配 path

# 三、跨子域共享

Cookie 的 domain 属性决定了其在不同子域之间的共享范围。

domain 设置 可用范围 示例
domain=test.example.com 仅在 test.example.com 及其子域下可用 test.example.com ✅ 可用
sub.test.example.com ✅ 可用
eagle.example.com ❌ 不可用
domain=.example.com(注意前面的点) example.com 的所有一级子域之间共享 test.example.com ✅ 可用
eagle.example.com ✅ 可用
www.example.com ✅ 可用
  • 最佳实践:为了在多个子域(如 www.a.comapp.a.com)之间共享登录状态,应将 domain 设置为顶级域名,如 domain=.a.com

# 跨子域操作能力(读取/修改/新增)

  • 前提Domain=.example.com 且当前路径命中 Path;非 HttpOnly 才能被 JS 读取/修改;Secure 仅在 HTTPS 下可写。
  • 读取:其他子域(如 eagle.example.com)可读取命中 domain/path 的非 HttpOnly Cookie。
  • 修改(覆盖):其他子域可通过相同 name + domain + path 覆盖该 Cookie 的值,变更对所有子域生效。
  • 新增:其他子域可新增 Domain=.example.com 的 Cookie,使其对所有子域可见。

# 示例(跨子域共享)

  • test.example.com 设置共享 Cookie:
document.cookie = "uid=1; domain=.example.com; path=/";

  • eagle.example.com 读取:
console.log(document.cookie); // "uid=1"(非 HttpOnly 才能看到)

  • eagle.example.com 修改(覆盖):
document.cookie = "uid=2; domain=.example.com; path=/"; // 覆盖 uid

  • eagle.example.com 新增:
document.cookie = "theme=dark; domain=.example.com; path=/";

  • 回到 test.example.com 读取:
console.log(document.cookie); // "uid=2; theme=dark; ..."


# 四、跨页面影响

不同页面对 Cookie 的操作是否会互相影响,完全取决于这些 Cookie 的 domainpath 是否相同。

[!TIP] 核心结论:只有当 domainpath 完全相同时,我们才说它们是“同一个 Cookie”。

  • 修改:✅ 全局生效。在任一符合条件的页面修改,所有其他符合条件的页面都能看到新值。
  • 删除:✅ 全局生效。在一个页面删除,所有相关页面都将无法访问该 Cookie。
  • 修改:❌ 互不影响。修改其中一个,另一个同名但 domain/path 不同的 Cookie 不会改变。
  • 删除:❌ 无法删除。尝试删除一个 domain/path 不匹配的 Cookie 会静默失败。
  • 读取:❌ 互相隔离。页面只能读取其 domainpath 范围内的 Cookie。

# 五、HttpOnly 专栏

HttpOnly 是一个专门为增强安全性而设计的 Cookie 属性。

操作/能力 是否允许 说明
JavaScript 读取 ❌ 不允许 document.cookie 看不到它。
JavaScript 修改/删除 ❌ 不允许 任何客户端脚本操作都会被忽略。
浏览器自动发送 ✅ 允许 在每次向匹配的服务器发送 HTTP 请求时,浏览器会自动携带此 Cookie。
跨子域共享 ✅ 允许 只要 domain 属性设置正确(如 .example.com),HttpOnly Cookie 同样可以在子域间共享。
  • 核心用途:防止 XSS (跨站脚本) 攻击。即使页面被注入了恶意脚本,该脚本也无法窃取到 HttpOnly 的 Cookie(如 session id)。

# 适用范围(补充)

  • HttpOnly 的作用范围是“单个 Cookie(一个 key=value)”,不是某个域名或整个浏览器的全局开关;每个 Cookie 是否带 HttpOnly 由服务端通过 Set-Cookie 单独决定。
  • JS 仅能读取/修改非 HttpOnly 的 Cookie,无法通过 document.cookie 创建或修改带 HttpOnly 的 Cookie。
  • 浏览器请求会自动携带所有命中 domain/path 的 Cookie,包括 HttpOnly 和非 HttpOnly;因此接口请求能看到全部匹配的 Cookie,而 JS 只能看到其中非 HttpOnly 的部分。
  • 是否添加或移除 HttpOnly 只能通过服务端 Set-Cookie 完成;前端代码无法为已有 Cookie 增减 HttpOnly 属性。

# 示例(HttpOnly)

  • 服务端设置(决定是否 HttpOnly):
Set-Cookie: sessionid=abc123; Path=/; Domain=.example.com; HttpOnly; Secure; SameSite=Lax

  • JS 读取对比(只能看到非 HttpOnly):
document.cookie = "a=1; path=/; domain=.example.com";
console.log(document.cookie); // "a=1"(看不到 HttpOnly 的 sessionid)

  • 接口请求会自动携带全部命中的 Cookie(含 HttpOnly):
fetch("https://test.example.com/api/me", { credentials: "include" });
// 请求头将自动包含:Cookie: a=1; sessionid=abc123(命中 domain/path 即携带)

  • 删除 / 登出流程(前端无法变更 HttpOnly):
// 前端试图删除 HttpOnly:
document.cookie = "sessionid=; Max-Age=0; path=/; domain=.example.com"; // ❌ 无法删除原 HttpOnly 的 sessionid

// 正确做法:后端回包删除
Set-Cookie: sessionid=; Max-Age=0; Path=/; Domain=.example.com; HttpOnly

  • 结论HttpOnly 只能由服务端通过 Set-Cookie 控制;JS 只能读改非 HttpOnly,请求会携带所有命中的 Cookie(包含 HttpOnly)。

# 六、常见问题与陷阱

# 1. “修改”失败,实为“新建”

当尝试修改一个 Cookie,但提供的 domainpath 与原 Cookie 不符时,浏览器不会修改,而是会创建一个新的、同名的 Cookie。 示例:

  • 已有 Cookiekey=1; domain=.example.com; path=/admin
  • 你的代码document.cookie = "key=2; path=/"
  • 最终结果:浏览器中会同时存在两个名为 key 的 Cookie:
    • key=1; domain=.example.com; path=/admin
    • key=2; domain=.example.com; path=/ (因为未指定 domain,默认使用当前页面的 domain)

# 2. 删除失败

最常见的原因是删除时指定的 domainpath 与原 Cookie 不一致。请务必检查浏览器开发者工具中 Cookie 的确切 domainpath 值。

如果因为路径或域名的差异,导致浏览器中存在多个同名 Cookie,浏览器会将它们全部发送到服务器(在 Cookie 请求头中以分号分隔)。服务端应用程序在解析这个字符串时,其行为可能是不确定的,它可能会取第一个、最后一个,或导致解析错误,从而引发难以排查的 BUG。

# 七、本质总结

[!IMPORTANT] 一个 Cookie 是否可操作(读/写)、是否跨域、是否会互相影响,归根结底只取决于三个核心属性:HttpOnlyDomainPath

Secure 属性仅作为写入前置条件,不影响已存在 Cookie 的读取和作用范围。

【未经作者允许禁止转载】 Last Updated: 4/7/2026, 7:41:05 AM