Cookie

Set-Cookie 的七个属性、Cookie 请求语法、SameSite 与 __Host- 前缀规则。

作者 David更新于 第 19 篇(共 22 篇)

规范基准 RFC 6265(及其修订草案 6265bis)。Cookie 不属于 HTTP 核心语义(RFC 9110),是独立的状态管理层。

set-cookie        = cookie-pair *( ";" SP cookie-av )
cookie-pair       = cookie-name "=" cookie-value
cookie-name       = token
cookie-value      = *cookie-octet / ( DQUOTE *cookie-octet DQUOTE )
cookie-octet      = %x21 / %x23-2B / %x2D-3A / %x3C-5B / %x5D-7E
Set-Cookie: sid=abc123; Path=/; Secure; HttpOnly; SameSite=Lax; Max-Age=3600

硬性规则:

  • 每个 Cookie 一个 Set-Cookie 字段行。该字段 MUST NOT 被合并成逗号分隔的单行——其 Expires 值内部含逗号,合并即破坏解析。这是字段合并规则的头号例外。
  • cookie-value 不得含空白、逗号、分号、反斜杠。需要这些字符时自行做百分号或 Base64 编码——规范不定义任何编码。
  • 属性名大小写不敏感;未知属性 MUST 被忽略。
  • 属性顺序无意义,但同名属性以最后一个为准。

七个属性

Expires

Expires = <sane-cookie-date>

绝对过期时刻(IMF-fixdate)。无 Expires 且无 Max-Age → 会话 Cookie,浏览器关闭即删。

设为过去的时间是删除 Cookie 的标准做法——且删除时的 Path/Domain 必须与设置时完全一致,否则删不掉(高频 bug)。

Max-Age

Max-Age = [ "-" ] 1*DIGIT

相对秒数。优先级高于 Expires——两者同时存在时 Max-Age 胜出(不受客户端时钟偏差影响)。

Max-Age=0 或负值 → 立即删除。

Domain

Set-Cookie: a=1; Domain=example.com

反直觉规则:

  • 指定 Domain → Cookie 对该域及其所有子域可见(example.com + www.example.com + api.example.com)。
  • 不指定 Domain → 仅对当前精确主机可见,不含子域。不指定反而更严格。
  • 前导点(Domain=.example.com)在 6265 中被忽略,等价于无点形式。
  • 不得设为公共后缀(.com、.co.uk)或上级无关域——浏览器按 Public Suffix List 拒绝。

Path

Set-Cookie: a=1; Path=/admin
  • 匹配规则:请求路径等于该值,或以该值加 / 为前缀。Path=/admin 匹配 /admin、/admin/x,不匹配 /administrator。
  • 缺省值由请求 URI 推导:取最后一个 / 之前的部分(/a/b/c → /a/b),而非 /。
  • Path 不是安全边界——同源不同路径的脚本可通过 iframe 等方式互访。不要用它做隔离。

Secure

仅通过安全传输(HTTPS)发送。

注意:Secure 只防「明文发出」,不防「被明文写入」——非安全来源的脚本仍可能覆盖同名 Cookie(除非用 __Secure- 前缀)。

HttpOnly

禁止 JavaScript(document.cookie)访问。是防 XSS 窃取会话的基本手段,会话 Cookie 必须开启。

SameSite

SameSite = "Strict" / "Lax" / "None"

控制跨站请求是否携带:

值行为
Strict任何跨站请求都不携带,含从外站点击链接跳入
Lax跨站的顶层导航 GET 携带;跨站 POST、iframe、img、XHR 不携带
None始终携带,MUST 同时带 Secure,否则浏览器拒绝

现代浏览器在缺省时按 Lax 处理(6265bis 方向),但该默认不是规范强制,应显式声明。

SameSite=Lax 已可挡住大部分 CSRF,但不能替代 CSRF token——它不防同站攻击,且旧客户端不支持。

Cookie(请求字段)

cookie-header = "Cookie:" OWS cookie-string OWS
cookie-string = cookie-pair *( ";" SP cookie-pair )
Cookie: sid=abc123; theme=dark; lang=zh

关键差异:

  • 只发名值对,不发任何属性——服务端无法从请求得知某 Cookie 的 Domain、Path、Secure 等。
  • 分隔符是 ; (分号加空格),不是逗号。
  • 多个同名 Cookie(不同 Domain/Path)可以同时出现,且顺序不保证、无法区分来源——这是「Cookie 覆盖/投毒」类攻击的基础。
  • 所有 Cookie 在同一个 Cookie 字段中发送(不像 Set-Cookie 每个一行)。
  • 无 Cookie 时不发该字段(不发空字段)。

安全前缀

浏览器对特定名字前缀强制附加约束:

前缀强制要求
__Secure-必须带 Secure,且由安全来源设置
__Host-必须带 Secure、Path=/、且不得带 Domain,由安全来源设置
Set-Cookie: __Host-sid=abc; Path=/; Secure; HttpOnly; SameSite=Lax

__Host- 是最强形式:它保证该 Cookie 只属于当前精确主机,子域无法写入或覆盖——能挡住子域接管类攻击。会话 Cookie 应优先使用。

容量限制

规范建议的下限(浏览器实际值接近):

  • 每个 Cookie ≥ 4096 字节(名 + 值 + 属性总长)。
  • 每个域 ≥ 50 个。
  • 总数 ≥ 3000 个。

超限时浏览器按最近最少使用淘汰,静默丢弃——不会有任何错误提示。Cookie 过大还会显著拖慢每个请求(每请求都全量携带)。

下一篇:上下文与控制字段。

本页目录