本文整理自 MDN: HTTP Cookie 与 RFC 6265: HTTP State Management Mechanism。
一、什么是 Cookie
HTTP Cookie(也称 Web Cookie、浏览器 Cookie)是服务器通过 HTTP 响应发送到用户浏览器并保存在本地的一小块数据。浏览器会存储这些 Cookie,并在下次向同一服务器再发起请求时,通过请求头自动携带发送。通常用于告知服务端:两个请求是否来自同一浏览器,从而在无状态的 HTTP 协议上维持稳定状态(如保持用户登录)[MDN]。
- 发明与历史:Lou Montulli(Netscape,1994);RFC 2109、RFC 2965 已被 RFC 6265(2011)取代,Cookie2/Set-Cookie2 已废弃 [RFC 6265]。
- 标准:RFC 6265 定义
Cookie与Set-Cookie两个头部,并指出 Cookie 存在诸多历史遗留的安全与隐私问题,但仍被广泛使用。
二、Cookie 的三大用途 [MDN]
| 用途 | 说明 |
|---|---|
| 会话状态管理 | 用户登录状态、购物车、游戏分数等需记录的信息 |
| 个性化设置 | 用户自定义设置、主题等 |
| 浏览器行为跟踪 | 跟踪与分析用户行为(常涉及隐私与合规) |
注意:Cookie 曾作为客户端唯一存储手段被滥用;现在若不需要在每次请求中携带数据,推荐使用现代存储 API(如 Web Storage、IndexedDB),以减少请求头体积与性能开销,尤其在移动端 [MDN]。 在浏览器中查看 Cookie:开发者工具 → 存储/Storage → Storage Inspector → 选中 Cookie [MDN]。
三、创建与传递:Set-Cookie 与 Cookie 头
3.1 基本流程
- 服务器在 HTTP 响应头里添加一个或多个 Set-Cookie。
- 浏览器保存这些 Cookie,之后向同一服务器发请求时,在 Cookie 请求头里一并发送 [MDN]。
示例 [MDN]:
HTTP/1.0 200 OK
Content-type: text/html
Set-Cookie: yummy_cookie=choco
Set-Cookie: tasty_cookie=strawberry
[页面内容]
后续请求:
GET /sample_page.html HTTP/1.1
Host: www.example.org
Cookie: yummy_cookie=choco; tasty_cookie=strawberry
注意:不应将多个 Set-Cookie 折叠成一行(HTTP 头部折叠可能改变语义,因为逗号在 Set-Cookie 中有特殊含义)[RFC 6265]。 服务端如何设置 Set-Cookie 可参考 MDN 示例:PHP、Node.js、Python、Ruby on Rails 等 [MDN]。
3.2 语法概要(RFC 6265)
- Set-Cookie 格式:
Set-Cookie: <cookie-name>=<cookie-value>,后可跟若干属性(; Expires=...、; Max-Age=...、; Domain=...、; Path=...、; Secure、; HttpOnly等)。 - Cookie 请求头:
Cookie: cookie-pair *( "; " cookie-pair ),仅包含名值对,不包含过期时间、域、路径、Secure、HttpOnly 等属性,服务端无法从 Cookie 头 alone 得知这些元数据 [RFC 6265]。
四、Cookie 的生命周期
4.1 会话期 vs 持久性 [MDN][RFC 6265]
-
会话期 Cookie(Session Cookie)
- 不设置
Expires且不设置Max-Age(或Max-Age=0)。 - 在当前会话结束后被删除。注意:“当前会话”由浏览器定义,部分浏览器在重启时会做会话恢复,可能导致会话 Cookie 被保留更久 [MDN]。
- RFC 6265:此类 Cookie 的
persistent-flag为 false,expiry-time为“会话结束”。
- 不设置
-
持久性 Cookie(Persistent Cookie)
- 通过
Expires(日期/时间)或Max-Age(秒数)指定存活期。 - 在过期前会一直存在(除非用户或浏览器策略清除)。
- Max-Age 优先于 Expires;若两者都存在,以 Max-Age 为准。若 Max-Age 为 0 或负数,表示立即过期 [RFC 6265]。
- 通过
示例 [MDN]:
Set-Cookie: id=a3fWa; Expires=Wed, 21 Oct 2015 07:28:00 GMT;
重要:Expires 的日期时间是客户端解释的,与服务器时区无关 [MDN]。
若站点对用户做身份验证,建议在每次验证时重新生成并重新发送会话 Cookie(包括已存在的),以减轻会话固定攻击(Session Fixation)[MDN]。
4.2 删除 Cookie
服务端可通过发送同名、同 Domain、同 Path 的 Cookie,并将 Expires 设为过去的时间(或 Max-Age=0)来删除 Cookie [RFC 6265][MDN]。
五、限制 Cookie 的访问与发送
5.1 Secure
- 带
Secure的 Cookie 仅应通过安全通道(通常为 HTTPS/TLS)发送,不会在不安全的 HTTP 请求中发送(本地主机除外)[MDN]。 - 不安全的站点(URL 为
http:)无法设置带Secure的 Cookie [MDN]。 - 注意:Secure 只保护机密性(传输中不被窃听),不提供完整性。主动网络攻击者仍可能通过不安全通道注入或覆盖 Cookie,破坏其完整性 [RFC 6265]。
5.2 HttpOnly
- 带
HttpOnly的 Cookie 不能被 JavaScript 的document.cookie等“非 HTTP API”访问,仅用于 HTTP 请求 [MDN][RFC 6265]。 - 服务端会话 Cookie 通常不需要对 JS 可见,应设置
HttpOnly,以缓解 XSS 窃取会话 [MDN]。
示例 [MDN]:
Set-Cookie: id=a3fWa; Expires=Wed, 21 Oct 2015 07:28:00 GMT; Secure; HttpOnly
六、定义 Cookie 的发送范围:Domain、Path、SameSite
6.1 Domain [MDN][RFC 6265]
- 不指定 Domain:默认为当前 host,不包含子域(即仅当前域名)。
- 指定 Domain:如
Domain=mozilla.org,则子域(如developer.mozilla.org)也会收到该 Cookie。指定 Domain 会扩大作用域。 - 用户代理会拒绝 Domain 不包含当前 origin 的 Cookie;许多浏览器还会拒绝将 公共后缀(如
com、co.uk)设为 Domain,以防止恶意站点为整片顶级域设置 Cookie [RFC 6265]。
6.2 Path [MDN][RFC 6265]
- Path 指定 URL 路径前缀;只有请求的 URL 路径与该 Path 匹配(或为其子路径)时才会发送 Cookie。
- 路径以
%x2F("/")为分隔符;子路径会匹配。例如Path=/docs会匹配:/docs、/docs/、/docs/Web/、/docs/Web/HTTP
- 不匹配:
/、/docsets、/fr/docs[MDN]。 - 若省略 Path,默认值为当前请求 URI 的路径的“目录”部分 [RFC 6265]。
- 安全提醒:Path 不能作为安全边界依赖;同一主机上不同路径的互不信任服务不应仅靠 Path 隔离敏感 Cookie [RFC 6265]。
6.3 SameSite [MDN]
- SameSite 控制是否在跨站请求中发送 Cookie(“站点”由注册域和协议 http/https 共同定义),用于减轻 CSRF。
- 取值:
- Strict:仅在同站请求中发送。
- Lax:与 Strict 类似,但在用户从外站导航到该站时(如点击链接)也会发送。
- None:同站与跨站请求都会发送;必须同时设置
Secure(即仅在安全上下文中)[MDN]。
- 未设置 SameSite 时,现代浏览器多将其视为 Lax(此前默认行为是更宽松的“始终发送”)[MDN]。
- 同一注册域下,若协议不同(
httpvshttps),视为不同站点 [MDN]。
示例:
Set-Cookie: mykey=myvalue; SameSite=Strict
七、Cookie 前缀(__Host- 与 __Secure-)[MDN]
由于 Cookie 机制无法让服务端确认 Cookie 是否在安全来源设置、甚至无法确认最初设置者,子域上的漏洞可能通过 Domain 为父域设置 Cookie,被用于会话劫持。作为深度防御,可使用 Cookie 前缀:
-
__Host- 仅当同时满足以下条件时,浏览器才接受 Set-Cookie:
- 带 Secure;
- 从安全来源发送;
- 不包含
Domain; - Path 为
/。 此类 Cookie 可视为“锁定到当前 host”。
-
__Secure- 仅当带 Secure 且从安全来源发送时才接受,限制弱于
__Host-。
不符合前缀要求的 Cookie 会被浏览器拒绝。应用服务器必须校验完整 Cookie 名称;用户代理在发送 Cookie 头时不会去掉前缀 [MDN]。
八、浏览器存储模型与发送规则(RFC 6265 要点)
- 用户代理为每个 Cookie 存储:name、value、expiry-time、domain、path、creation-time、last-access-time、persistent-flag、host-only-flag、secure-only-flag、http-only-flag。
- 发送 Cookie 时:只发送与请求的 host(或 Domain 匹配)、Path 匹配、未过期、且满足 Secure(若为 secure-only)的 Cookie;若通过“非 HTTP API”生成请求(如
document.cookie),则不包含 http-only-flag 为 true 的 Cookie。 - Eviction(驱逐):过期 Cookie 会先被删除;若单域或全局 Cookie 数量超限,可按实现定义的策略删除(RFC 建议优先删过期,再删同域过多的,再删全局过多的;同优先级时删 last-access-time 最早的)。
- 实现建议下限:每 Cookie 至少 4096 字节(名+值+属性总长)、每域至少 50 个 Cookie、全局至少 3000 个 Cookie;服务端应尽量少而小,并做好用户代理未返回某些 Cookie 时的降级 [RFC 6265]。
九、JavaScript 与 Document.cookie [MDN]
- 通过 Document.cookie 可创建新 Cookie,也可读取现有 Cookie(仅限未设置
HttpOnly的)。 - 由 JavaScript 创建的 Cookie 不能包含
HttpOnly[MDN]。
示例 [MDN]:
document.cookie = "yummy_cookie=choco";
document.cookie = "tasty_cookie=strawberry";
console.log(document.cookie);
// 输出 "yummy_cookie=choco; tasty_cookie=strawberry"
安全:Cookie 值可被用户或脚本访问与修改,需注意 XSS。敏感场景建议使用服务端查证的不透明标识符,或考虑 JWT 等替代方案;在不可信环境中不要通过 HTTP Cookie 存储或传输敏感信息 [MDN]。
十、安全考量 [MDN][RFC 6265]
10.1 缓解措施
- 使用 HttpOnly 防止通过 JS 读取 Cookie。
- 敏感 Cookie(如身份验证)应生存期短,并设置 SameSite=Strict 或 Lax,避免在跨站请求中发送 [MDN]。
10.2 常见风险
- 环境权威(Ambient Authority)与 CSRF:Cookie 随请求自动携带,易被跨站请求伪造;应配合 SameSite、CSRF Token 等 [RFC 6265]。
- 明文传输:非 HTTPS 时 Cookie 明文传输,易被窃听与篡改;敏感 Cookie 应配合 Secure 与 HTTPS [RFC 6265]。
- 会话固定(Session Fixation):攻击者将已知会话 ID 植入受害者浏览器 → 受害者用该 ID 登录 → 攻击者用同一 ID 冒充。缓解:每次认证后重新签发会话 Cookie [MDN][RFC 6265]。
- 弱机密性:Cookie 不按端口、不按协议(http/https)隔离,同一 host 不同端口/协议可能共享 Cookie;不可在同一主机上对互不信任的服务依赖 Cookie 做敏感隔离 [RFC 6265]。
- 弱完整性:同父域下不同子域可互相覆盖 Domain 为父域的 Cookie;主动攻击者还可通过 HTTP 响应注入 Set-Cookie,影响 HTTPS 站点的 Cookie。加密/签名 Cookie 内容可部分缓解,但无法防止重放 [RFC 6265]。
- 依赖 DNS:Cookie 安全依赖 DNS;DNS 被篡改时,Cookie 提供的安全属性可能失效 [RFC 6265]。
十一、跟踪与隐私 [MDN][RFC 6265]
11.1 第一方 vs 第三方 Cookie
- 第一方 Cookie:Cookie 的域和协议与当前页面一致(或为当前页面的子域等符合 Domain 规则)。
- 第三方 Cookie:由页面中引用的其他域(如广告、统计)设置;同一第三方在不同站点可收到同一 Cookie,从而跨站跟踪用户 [MDN][RFC 6265]。
- 许多浏览器已限制或计划淘汰第三方 Cookie(如 Firefox 默认阻止已知跟踪器);服务器可通过 SameSite 控制是否在跨站场景下发送 [MDN]。
11.2 法规与合规 [MDN]
涉及 Cookie 的法规包括(具有全球影响):
- 欧盟 GDPR(通用数据保护条例)
- 欧盟 ePrivacy 指令
- 加州 CCPA(加州消费者隐私法;通常适用于年收入超过一定规模的实体)
常见要求:向用户告知使用 Cookie、允许用户拒绝部分或全部 Cookie、在用户拒绝 Cookie 时仍能使用主要服务。部分公司提供“Cookie 横幅”等方案以辅助合规 [MDN]。
11.3 各浏览器对第三方 Cookie 的政策(按浏览器与版本)
不同浏览器、不同版本对第三方 Cookie 的限制差异很大;以下按浏览器与版本范围整理,便于兼容性判断与迁移规划。策略会随版本更新变化,以各厂商官方文档为准。
Safari(WebKit)
| 时间 / 版本 | 策略概要 |
|---|---|
| 2017 年 6 月(ITP 1.0) | 引入 Intelligent Tracking Prevention (ITP):用机器学习识别跨站跟踪域并限制其 Cookie;未访问站点 30 天后清除其 Cookie;第三方上下文中对 Cookie 做分区。 |
| 2019 年 2 月(ITP 2.1) | 强化对已知跟踪域的限制与分类。 |
| 2019 年 4 月(ITP 2.2) | 防止通过链接装饰(URL 参数/片段)跨站跟踪:被分类域通过带 query/fragment 的链接导航时,通过 document.cookie 创建的持久 Cookie 寿命被限制为约 1 天。 |
| 2019 年 9 月(ITP 2.3) | 所有脚本可写的网站数据(含 Cookie、Storage)在从被分类域导航后,寿命上限为 7 天;document.referrer 降级为 eTLD+1,减少通过 referrer 泄露点击 ID。 |
| 2020 年 3 月(Safari 13.1 / iOS 13.4 / iPadOS 13.4) | 默认全面阻止所有第三方 Cookie(无例外),成为主流浏览器中首个默认全阻的;同时限制脚本可写存储的 7 天寿命、禁用登录指纹等。跨站嵌入若需 Cookie,需通过 Storage Access API 向用户请求授权。 |
小结:Safari 13.1+(macOS/iOS/iPadOS 对应版本起)默认即“全阻”第三方 Cookie;更早版本通过 ITP 逐步收紧,仍以“限制跟踪域 + 分区/短期”为主,而非一刀切全阻。
Firefox
| 时间 / 版本 | 策略概要 |
|---|---|
| 2019 年 6 月 | Enhanced Tracking Protection (ETP) 对新安装默认开启;2019 年 9 月推广到所有用户。默认阻止已知跟踪器、指纹等,对第三方 Cookie 按“跟踪列表”限制。 |
| 2021 年 2 月 | 引入 Total Cookie Protection (TCP):为每个网站维护独立“Cookie 罐”,第三方 Cookie 不能跨站共享,实质阻止跨站跟踪。初期主要在严格模式或可选开启。 |
| 2022 年 6 月 | TCP 开始向更多用户默认推广。 |
| 2024–2025 年 | Total Cookie Protection 在标准模式(Standard)下默认开启,逐步覆盖所有平台(Windows、macOS、Linux、Android),第三方 Cookie 按站点隔离,无法用于跨站跟踪。 |
小结:Firefox 当前(ETP 默认 + TCP 默认)下,第三方 Cookie 被“按站隔离”,等同阻止跨站跟踪;用户仍可在设置中按站点允许 Cookie。
Chrome(Chromium)
| 时间 / 版本 | 策略概要 |
|---|---|
| 2020 年 2 月(Chrome 80) | SameSite 默认行为变更:未指定 SameSite 的 Cookie 视为 SameSite=Lax,跨站子请求(如 iframe、img)不再携带这些 Cookie;需跨站携带必须显式 SameSite=None; Secure。同年 4 月曾因疫情短暂回滚,7 月恢复。 |
| 2020–2024 年 | 不默认阻止第三方 Cookie;仅无痕模式或用户手动在 chrome://settings 中开启“阻止第三方 Cookie”时才会阻。原计划 2022/2023 淘汰第三方 Cookie 并推 Privacy Sandbox(如 FLoC),多次推迟。 |
| 2024–2025 年 | 在部分渠道(约 1% 稳定版、约 20% Canary/Dev/Beta)试验性限制第三方 Cookie;计划从 2025 年起继续推进第三方 Cookie 弃用,与 Privacy Sandbox(CHIPS 分区 Cookie、Storage Access API、Related Website Sets、FedCM 等)配合,具体时间表以 Google 开发者公告为准。 |
小结:Chrome 目前仍以 SameSite 默认 Lax 为主,未全局默认“阻第三方”;淘汰时间表与 Privacy Sandbox 绑定,会随政策与反馈调整。
Microsoft Edge(Chromium)
| 时间 / 版本 | 策略概要 |
|---|---|
| 2019 年 12 月(Edge 79) | 引入 Tracking Prevention:三档——Basic(仅恶意跟踪/挖矿等)、Balanced(默认)、Strict。Balanced 基于“站点参与度”阻止未互动站点的跟踪器,并扩大阻止类别(如 Content 类)。 |
| 2020 年 1 月(Edge 80) | 跟踪防护默认开启,与 Chrome 的 SameSite 变更同期。 |
| Edge 77+ | 企业策略 BlockThirdPartyCookies 可强制在普通浏览中阻止第三方 Cookie(InPrivate 不受该策略约束)。 |
小结:Edge 默认不“全阻”第三方 Cookie,而是按跟踪列表 + 参与度启发式限制;Strict 模式最严,Balanced 在隐私与兼容之间折中。
其他浏览器(简要)
- Brave:自 2019 年 11 月 1.0 起默认阻止广告与跟踪器,第三方跟踪 Cookie 默认被阻。
- Opera:约 2019 年 10 月起内置反跟踪,策略类似“阻止已知跟踪列表”,非全阻第三方 Cookie。
汇总表(当前默认行为,约 2024–2025)
| 浏览器 | 默认是否阻止/限制第三方 Cookie | 说明 |
|---|---|---|
| Safari(13.1+) | ✅ 默认全部阻止 | 跨站嵌入需 Storage Access API 申请权限。 |
| Firefox(ETP+TCP 默认) | ✅ 按站隔离,等同阻止跨站跟踪 | 每站独立 Cookie 罐,第三方无法跨站共享。 |
| Chrome | ❌ 不默认阻止 | SameSite 默认 Lax;淘汰计划进行中,部分用户已进入试验限制。 |
| Edge | ⚠️ 默认限制跟踪器,非全阻 | Balanced 默认;Strict 最严。 |
| Brave | ✅ 默认阻止跟踪 Cookie | 与广告拦截一体。 |
开发建议:若依赖跨站 Cookie(如嵌入式登录、跨站分析),应显式设置 SameSite=None; Secure,并尽早评估 Storage Access API、CHIPS(Partitioned Cookie)、Related Website Sets 等替代方案,以兼容 Safari 与未来 Chrome 的变更。
十二、其他浏览器存储方式 [MDN]
| 机制 | 说明 |
|---|---|
| Web Storage | sessionStorage(会话、关标签即清)与 localStorage(长期);容量大于 Cookie,且不会随每次请求发送到服务器。 |
| IndexedDB | 存储更大量、结构化数据。 |
“僵尸”Cookie(Zombie Cookie):在 Cookie 被删后通过其他存储或脚本重新创建 Cookie。此类做法损害用户隐私与控制权,可能违反数据隐私法规并带来法律风险,不应使用 [MDN]。
十三、小结
- Cookie 由服务端通过 Set-Cookie 下发,浏览器在后续符合域、路径、安全、SameSite 等条件的请求中通过 Cookie 头自动携带,用于在无状态 HTTP 上维持状态 [MDN][RFC 6265]。
- 通过 Expires/Max-Age、Domain、Path、Secure、HttpOnly、SameSite 及前缀 __Host- / __Secure- 可控制生命周期、作用域与安全性。
- 在浏览器中,发送逻辑由用户代理按 RFC 与扩展(如 SameSite)实现;JS 仅能读写非 HttpOnly 的 Cookie。
- 建议:敏感 Cookie 使用 HttpOnly + Secure + SameSite,配合 CSRF 防护与短生存期;避免用 Cookie 存敏感明文;关注第三方 Cookie 限制与隐私法规。