# Cookie 字段详解

Cookie(HTTP Cookie) 是服务器发送到用户浏览器并存储在本地的一小段数据(通常不超过 4KB)。浏览器会在后续请求中自动携带 Cookie,用于实现用户身份识别、会话管理、个性化设置等功能。

Set-Cookie HTTP 响应标头用于将 cookie 由服务器发送到用户代理,以便用户代理在后续的请求中可以将其发送回服务器。

# 无效域名

如果 cookie 的域名不包含设置该域名的服务器,则其应该被用户代理拒绝。

在主域名的请求为其子域名设置的 cookie 也会被拒绝。

# 跨站限制

参考 SameSite

# XMLHttpRequest.withCredentials

XMLHttpRequest.withCredentials 属性是一个布尔值,它指示了是否该使用类似 cookie、Authorization 标头或者 TLS 客户端证书等凭据进行跨站点访问控制(Access-Control)请求。默认值是 false。

除非在发送 XMLHttpRequest 请求之前,将 withCredentials 设置为 true,否则来自不同域的 XMLHttpRequest 响应无法为自己的域设置 cookie 值。

TIP

不同域下的 XmlHttpRequest 响应,不论其 Access-Control- 标头设置什么值,都无法为它自身站点设置 Cookie 值,除非它在请求之前将 withCredentials 设为 true。

因此在跨域请求中使用 Set-Cookie 来设置 cookie 时,请注意将 withCredentials 设置为 true。

# Expires

以 HTTP 日期时间戳形式指定的 cookie 的最长有效时间

如果没有指定,那么会是一个会话期 cookie。会话在客户端被关闭时结束。

# Max-Age

在 cookie 过期之前需要经过的秒数。秒数为 0 或负值将会使 cookie 立刻过期。

Max-Age 的优先级高于 Expires

# HttpOnly

阻止 JavaScript 通过 Document.cookie 属性访问 cookie。

# Secure

仅当请求通过 https 发送时才会携带该 cookie

# SameSite

Cookie 的 SameSite 属性用来限制第三方 Cookie,从而减少安全风险。

它可以设置三个值。

  • Strict
  • Lax
  • None

# Strict

这意味浏览器仅对同一站点的请求发送 cookie,即请求来自设置 cookie 的站点 (opens new window)。如果请求来自不同的域名或协议(即使是相同域名),则携带有 SameSite=Strict 属性的 cookie 不会被发送。

站点

站点由域名的可注册域部分确定。可注册域由公共后缀列表中的一个条目加上它之前的域名部分组成。这意味着,例如 theguardian.co.uk、sussex.ac.uk 和 bookshop.org 都是可注册的域。也就是说相同的二级域名属于同一站点

# Lax

这意味着 cookie 不会在跨站请求中被发送,如:加载图像或框架(frame)的请求。但 cookie 在用户从外部站点导航到源站时,cookie 也会被发送(例如,访问一个链接)。这是 SameSite 属性未被设置时的默认行为。

请求类型 示例 正常情况 Lax(跨域时)
链接 <a href="..."></a> 发送 Cookie 发送 Cookie
预加载 <link rel="prerender" href="..."/> 发送 Cookie 发送 Cookie
GET 表单 <form method="GET" action="..."> 发送 Cookie 发送 Cookie
POST 表单 <form method="POST" action="..."> 发送 Cookie 不发送
iframe <iframe src="..."></iframe> 发送 Cookie 不发送
AJAX $.get("...") 发送 Cookie 不发送
Image <img src="..."> 发送 Cookie 不发送

# None

网站可以选择显式关闭SameSite属性,将其设为None。不过,前提是必须同时设置Secure属性(Cookie 只能通过 HTTPS 协议发送),否则无效。

仅在使用了安全(HTTPS)来源,并同时设置 secure 属性时才能使用名称中包含 __Secure- 或 __Host- 前缀的 cookie。

假如 cookie 以 __Host- 为前缀,那么 path 属性的值必须为 /(表示主机的任何路径),且不能含有 Domain 属性。

即 __Host- 只能设置在该请求自身的 Host