Skip to content

Cookie

概述

Cookie 是服务器保存在浏览器的一小段文本信息,一般大小不能超过4KB。浏览器每次向服务器发出请求,就会自动附上这段信息。

Cookie 主要保存状态信息,主要用途:

  • 对话(session)管理:保存登录、购物车等需要记录的信息。
  • 个性化信息:保存用户的偏好,比如网页的字体大小、背景色等等。
  • 追踪用户:记录和分析用户行为。

Cookie 不是一种理想的客户端储存机制。它的容量很小(4KB),缺乏数据操作接口,而且会影响性能。客户端储存应该使用 Web storage API 和 IndexedDB。

每次请求都需要让服务器知道的信息,才应该放在 Cookie 里面。

每个 Cookie 都有以下几方面的元数据。

  • Cookie 的名字
  • Cookie 的值(真正的数据写在这里面)
  • 到期时间(超过这个时间会失效)
  • 所属域名(默认为当前域名)
  • 生效的路径(默认为当前网址)

举例来说,用户访问网址www.example.com,服务器在浏览器写入一个 Cookie。这个 Cookie 的所属域名为www.example.com,生效路径为根路径/。如果 Cookie 的生效路径设为/forums,那么这个 Cookie 只有在访问www.example.com/forums及其子路径时才有效。以后,浏览器访问某个路径之前,就会找出对该域名和路径有效,并且还没有到期的 Cookie,一起发送给服务器。


用户可以设置浏览器不接受 Cookie,也可以设置不向服务器发送 Cookie。

window.navigator.cookieEnabled属性返回一个布尔值,表示浏览器是否打开 Cookie 功能。

window.navigator.cookieEnabled // true

document.cookie属性返回当前网页的 Cookie。

document.cookie // "id=foo;key=bar"

不同浏览器对 Cookie 数量和大小的限制,是不一样的。一般来说,单个域名设置的 Cookie 不应超过30个,每个 Cookie 的大小不能超过4KB。超过限制以后,Cookie 将被忽略,不会被设置。

服务器如果希望在浏览器保存 Cookie,就要在 HTTP 回应的头信息里面,放置一个Set-Cookie字段,浏览器会自动管理 Cookie

set-cookie 要一个个设置

txt
 HTTP/1.0 200 OK
 Content-type: text/html
 Set-Cookie: foo=bar
 Set-Cookie: id=a3fWa; Expires=Wed, 21 Oct 2015 07:28:00 GMT; Secure; HttpOnly
 ...

如果服务器想改变一个早先设置的 Cookie,必须同时满足四个条件:Cookie 的keydomainpathsecure都匹配。

浏览器向服务器发送 HTTP 请求时,每个请求都会带上相应的 Cookie。

cookie 里面,把所有符合要求的都附上了,用分号分隔

txt
GET /sample_page.html HTTP/1.1
Host: www.example.org
Cookie: foo=bar; tasty_cookie=strawberry

Secure 属性 指定浏览器只有在加密协议 HTTPS 下,才能将这个 Cookie 发送到服务器。另一方面,如果当前协议是 HTTP,浏览器会自动忽略服务器发来的Secure属性。

SameSite 属性 该属性用来限制第三方 Cookie 的发送,从而减少CSRF安全风险。可设置三个值:

  • Strit:完全禁止第三方 Cookie,跨站点时,任何情况下都不会发送 Cookie;过于严格,在一些链接跳转的时候不携带 Cookie 可能导致重新登录
  • Lax:除了导航到目标网址的Get 请求以外,大部分都不会发送第三方的 Cookie
  • None...

HTTPOnly 属性HttpOnly属性指定该 Cookie 无法通过 JavaScript 脚本拿到,主要是document.cookie属性、XMLHttpRequest对象和 Request API 都拿不到该属性。这样就防止了该 Cookie 被脚本读到,只有浏览器发出 HTTP 请求时,才会带上该 Cookie。

读取

document.cookie属性用于读写当前网页的 Cookie。

读取的时候,它会返回当前网页的所有非HTTPOnly Cookie,是一个;分隔的长字符串。

js
var cookies = document.cookie.split(';');
for (var i = 0; i < cookies.length; i++) {
 console.log(cookies[i]);
}
// foo=bar
// baz=bar

写入

document.cookie属性是可写的,可以通过它为当前网站添加 Cookie。

写入的时候,Cookie 的值必须写成key=value的形式。注意,等号两边不能有空格。另外,写入 Cookie 的时候,必须对分号、逗号和空格进行转义(它们都不允许作为 Cookie 的值),这可以用encodeURIComponent方法达到。

但是,document.cookie一次只能写入一个 Cookie,而且写入并不是覆盖,而是添加,这和服务器通过响应头设置 Cookie 是一样的,一次只能设置一个。

  1. document.cookie = 'test1=hello';
  2. document.cookie = 'test2=world';
  3. document.cookie
  4. // test1=hello;test2=world

写入 Cookie 的时候,可以同时写入 Cookie 的属性。

js
document.cookie = 'fontSize=14; '
  + 'expires=' + someDate.toGMTString() + '; 
  + 'path=/subdirectory;`
  + 'domain=*.example.com';

Cookie 的属性一旦设置完成,就没有办法读取这些属性的值

删除一个现存 Cookie 的唯一方法,是设置它的expires属性为一个过去的日期。

document.cookie = 'fontSize=;expires=Thu, 01-Jan-1970 00:00:01 GMT';