HTTP - Cookies
HTTP Cookie (web cookie, browser cookie) 是服务器发送到用户浏览器并保存在本地的一小块数据,它会在浏览器下次向该服务器发起请求时附加在请求首部 Cookie 字段发送给服务器。
Cookie 主要用于以下三个方面:
- 会话状态管理 (如用户登录状态、购物车、游戏分数或其它需要记录的信息等)
- 个性化设置 (如用户自定义设置、主题等)
- 浏览器行为跟踪 (如跟踪分析用户行为等)
Cookie 曾一度用于客户端数据的存储,因当时并没有其它合适的存储办法而作为唯一的存储手段,但现在随着现代浏览器开始支持各种各样的存储方式,Cookie 渐渐被淘汰。Cookie 的大小不超过 4KB,而且每次请求都会发送回服务器,带来额外的性能开销。新的浏览器 API 已经允许开发者直接将数据存储到本地,如使用 Web storage API
或更加高级的IndexedDB
。
创建 Cookie
当服务器收到 HTTP 请求时,服务器可以通过响应头部的 Set-Cookie
字段将 cookies 发送给客户端浏览器。浏览器收到响应之后,通常会保存下 cookies,之后对该服务器的每一次请求中都通过请求头部的 Cookie
字段将相应的 cookies 附带发送到服务器。
Set-Cookie
响应首部Set-Cookie
被用来由服务器端向客户端发送 cookies。
Syntax:1
2
3
4
5
6
7
8
9
10
11
12
13Set-Cookie: <cookie-name>=<cookie-value>
Set-Cookie: <cookie-name>=<cookie-value>; Expires=<date>
Set-Cookie: <cookie-name>=<cookie-value>; Max-Age=<non-zero-digit>
Set-Cookie: <cookie-name>=<cookie-value>; Domain=<domain-value>
Set-Cookie: <cookie-name>=<cookie-value>; Path=<path-value>
Set-Cookie: <cookie-name>=<cookie-value>; Secure
Set-Cookie: <cookie-name>=<cookie-value>; HttpOnly
Set-Cookie: <cookie-name>=<cookie-value>; SameSite=Strict
Set-Cookie: <cookie-name>=<cookie-value>; SameSite=Lax
// Multiple directives are also possible, for example:
Set-Cookie: <cookie-name>=<cookie-value>; Domain=<domain-value>; Secure; HttpOnly
<cookie-name>=<cookie-value>
cookies 键值对。<cookie-name>
,键名。可以是除了控制字符 (CTLs)、空格 (spaces) 或制表符 (tabs) 之外的任何 US-ASCII 字符。同时,不能够包含以下分隔字符:()<>@,;:\"/[]?={}
。<cookie-value>
,键值。可以是除了控制字符 (CTLS)、空格 (whitespace)、双引号 (double quotes)、逗号 (comma)、分号 (semicolon) 和反斜杠 (backslash) 之外的任意 US-ASCII 字符。该值可以也可以用双引号括起来,即cookie-name="cookie-value"
。关于编码:许多应用会对 cookie 值按照 URL 编码 (URL encoding) 规则进行编码,按照 RFC 规范,这不是必须的。不过编码可以将不规范的值转化为符合要求的值。__Secure-
前缀,以__Secure-
为前缀的 cookie,必须与secure
属性一同设置,同时必须应用于安全页面 (HTTPS)。__Host-
前缀,以__Host-
为前缀的 cookie,必须与secure
属性一起设置,必须应用于安全页面 (HTTPS),而且不能够设置domain
属性 (这样就不会发送给子域),同时path
属性的值必须为/
。1
2
3
4
5
6
7
8
9// 当响应来自于一个安全域(HTTPS)的时候,二者都可以被客户端接受
Set-Cookie: __Secure-ID=123; Secure; Domain=example.com
Set-Cookie: __Host-ID=123; Secure; Path=/
// 缺少 Secure 指令,会被拒绝
Set-Cookie: __Secure-id=1
// 缺少 Path=/ 指令,会被拒绝
Set-Cookie: __Host-id=1; Secure
// 由于设置了 domain 属性,会被拒绝
Set-Cookie: __Host-id=1; Secure; Path=/; domain=example.com
Expires=<date>
可选,指定 cookie 的有效日期,格式和Date
首部字段一样。注意:该有效日期是指客户端上的日期,不是服务端。如:1
Set-Cookie: id=a3fWa; Expires=Wed, 21 Oct 2015 07:28:00 GMT;
Max-Age=<non-zero-digit>
可选,指定 cookie 的有效时间,值为非零整数,单位为秒。如Max-Age=60
,表示 cookie 在 60 秒之后就会过期。Domain=<domain-value>
可选,指定 cookie 可以送达的主机。如果不指定,默认为当前文档访问地址 (Document.location
) 的主机,但是不包括子域名。如果指定了Domain
,在一般包括子域名。如,Domain=mozilla.org
,则 cookie 也可以发送到子域名中 (如developer.mozilla.org
)。Path=<path-value>
可选,指定 cookie 允许发送的 URL 路径。字符%x2F
(/
) 为路径分隔符,子路径也会被匹配。如Path=/docs
,则/docs
,/docs/Web/
,docs/Web/HTTP
等都会被匹配。Secure
可选,标记为Secure
的 Cookie 只应通过被 HTTPS 协议加密的请求发送给服务器。但即便设置了Secure
标记,敏感信息也不应该通过 Cookie 传输,因为 Cookie 有其固有的不安全性,Secure
标记无法提供确实的安全保障。从 Chrome 52 和 Firefox 52 开始,不安全的站点 (http:) 无法使用 Cookie 的Secure
属性。HttpOnly
可选,设置了HttpOnly
属性的 Cookie 不能使用 JavaScript 的Document.cookie
属性、XMLHttpRequest
或Request
API 进行访问,以防范跨站脚本攻击 (XSS)。
Cookie
Cookie 是请求首部,会将由服务器通过 Set-Cookie
响应首部发送过来的 cookies 发送到服务器。
这个首部可能会被完全移除,例如在浏览器的隐私设置为禁止用 cookie。1
Cookie: name=value[; name2=value2; name3=value3; ...]
如:1
Cookie: PHPSESSID=298zf09hf012fh2; csrftoken=u32t4o3tb3gg43; _gat=1;
会话期 cookies (Session cookies)
会话期 cookies ,即Set-Cookie
中不设置过期日期 (Expires
) 或有效时间 (Max-Age
) 的 cookies。会话期 cookies 会在浏览器关闭时自动删除。
需要注意的是,有些浏览器提供了会话恢复功能,这种情况下即使关闭了浏览器,会话期 cookies 也会被保留下来,就像浏览器从来没有关闭一样。1
Set-Cookie: sessionid=38afes7a8; HttpOnly; Path=/
持久化 cookies (Permanent cookies)
持久化 cookies,即指定了过期日期 (Expires
) 或有效时间 (Max-Age
) 的 cookies。持久化 cookies 与客户端关闭与否无关,只有过期了才会失效。1
Set-Cookie: id=a3fWa; Expires=Wed, 21 Oct 2015 07:28:00 GMT; Secure; HttpOnly
第三方 cookies
每个 cookie 都会有与之关联的域 (Domain),如果 cookie 的域和页面相同,那么我们称这个 cookie 为第一方 cookie (first-part cookie)。如果 cookie 的域和页面的域不同,则称之为第三方 cookie (third-part cookie)。 如,网站 A 上引用了网站 B 的一个 JS 脚本,当浏览器打开网站 A 的时候,也会请求网站 B 的这个脚本,这时候,网站 B 可以创建 cookie 一起响应返回。浏览器会将网站 B 的 cookie 也保存下来 (浏览器没有禁止第三方 cookie 的情况下),这个 cookie 相对网站 A 来说就是第三方 cookie,只有用户访问网站 B 的时候使用。
利用第三方 cookies 进行精准推送广告 (如百度联盟):
- 用户使用百度搜索的时候,百度搜索引擎会记住你的搜索内容,并设置了一个用户标识 cookie (BAIDUID)。
- 当用户访问嵌有百度推广广告的网页的时候,广告模块 (如
<iframe src="http://pos.baidu.com/...">
) 会携带这个 cookie 一起发送到服务器。然后,服务器根据这个用户标识找到你搜索过的内容,生成相应的广告返回。
DNT (Do-Not-Track)
DNT
请求首部字段表明了用户对于网站追踪的意愿。0
,表示用户同意目标站点追踪用户的个人信息;1
,表示用户不愿意目标站点追踪用户的个人信息。
用户对DNT
的设置,可以使用Navigator.doNotTrack
属性进行读取。