2.5 Cookie #
2.5.1 什么是 Cookie #
当用户通过浏览器第一次访问服务器的时候,服务器肯定是不知道他的身份的。所以,就要创建一个独特的身份标识数据,格式是 “key=value”,然后放进 Set-Cookie 字段里,随着响应报文一同发给浏览器。
浏览器收到响应报文,看到里面有 Set-Cookie,知道这是服务器给的身份标识,于是就保存起来,下次再请求的时候就自动把这个值放进 Cookie 字段里发给服务器。因为第二次请求里面有了 Cookie 字段,服务器就知道这个用户不是新人,之前来过,就可以拿出 Cookie 里的值,识别出用户的身份,然后提供个性化的服务。服务器有时会在响应头里添加多个 Set-Cookie,存储多个 “key=value”。但浏览器这边发送时不需要用多个 Cookie 字段,只要在一行里用 “;” 隔开就行。
2.5.2 Cookie 的属性 #
生存周期 #
Cookie 的生存周期,也就是它的有效期,让它只能在一段时间内可用,一旦超过这个期限浏览器就认为是 Cookie 失效,在存储里删除,也不会发送给服务器。
Cookie 的有效期可以使用 Expires 和 Max-Age 两个属性来设置。Expires 俗称过期时间,用的是绝对时间点,可以理解为截止日期(deadline)。Max-Age 用的是相对时间,单位是秒,浏览器用收到报文的时间点再加上 Max-Age,就可以得到失效的绝对时间。
Expires 和 Max-Age 可以同时出现,两者的失效时间可以一致,也可以不一致,但浏览器会优先采用 Max-Age 计算失效期。
如果不指定 Expires 或 Max-Age 属性,那么 Cookie 仅在浏览器运行时有效,一旦浏览器关闭就会失效,这被称为会话 Cookie (session cookie) 或内存 Cookie (in-memory cookie), 在 Chrome 浏览器里过期时间会显示为 “Session” 或 “N/A”。
作用域 #
Cookie 的作用域可以让浏览器仅发送给特定的服务器和 URI,避免被其他网站盗用。
作用域的设置比较简单,“Domain” 和 “Path” 指定了 Cookie 所属的域名和路径,浏览器在发送 Cookie 前会从 URI 中提取出 host 和 path 部分,对比 Cookie 的属性。如果不满足条件,就不会在请求头里发送 Cookie。
现实中为了省事,通常 Path 就用一个 “/” 或者直接省略,表示域名下的任意路径都允许使用 Cookie,让服务器自己去挑。
HttpOnly #
属性 “HttpOnly” 会告诉浏览器,此 Cookie 只能通过浏览器 HTTP 协议传输,禁止其他方式访问,浏览器的 JS 引擎就会禁用document.cookie
等一切相关的 API,脚本攻击也就无从谈起了。因为在 JS 脚本里可以用document.cookie
来读写 Cookie 数据,这就带来了安全隐患,有可能会导致 “跨站脚本”(XSS)攻击窃取数据。
SameSite #
属性 “SameSite” 可以防范 “跨站请求伪造”(XSRF)攻击,设置成 “SameSite=Strict” 可以严格限定 Cookie 不能随着跳转链接跨站发送,Cookie 仅在同站点请求中发送。而 “SameSite=Lax” 则略宽松一点,允许 GET/HEAD 等安全方法,但禁止 POST 跨站发送。当设置为 None 时,Cookie 将会在所有请求中发送,包括跨站点请求。
Secure #
属性 “Secure” 可以设置 Cookie 仅能用 HTTPS 协议加密传输,明文的 HTTP 协议会禁止发送。但 Cookie 本身不是加密的,浏览器里还是以明文的形式存在。