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 将被忽略,不会被设置。
HTTP 与 Cookie
浏览器基于 Response 自动设置 Cookie
服务器如果希望在浏览器保存 Cookie,就要在 HTTP 回应的头信息里面,放置一个Set-Cookie字段,浏览器会自动管理 Cookie
set-cookie 要一个个设置
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 的key、domain、path和secure都匹配。
Request 时浏览器自动携带 Cookie
浏览器向服务器发送 HTTP 请求时,每个请求都会带上相应的 Cookie。
cookie 里面,把所有符合要求的都附上了,用分号分隔
GET /sample_page.html HTTP/1.1
Host: www.example.org
Cookie: foo=bar; tasty_cookie=strawberryCookie 与安全
Secure 属性 指定浏览器只有在加密协议 HTTPS 下,才能将这个 Cookie 发送到服务器。另一方面,如果当前协议是 HTTP,浏览器会自动忽略服务器发来的Secure属性。
SameSite 属性 该属性用来限制第三方 Cookie 的发送,从而减少CSRF安全风险。可设置三个值:
Strit:完全禁止第三方 Cookie,跨站点时,任何情况下都不会发送 Cookie;过于严格,在一些链接跳转的时候不携带 Cookie 可能导致重新登录Lax:除了导航到目标网址的Get 请求以外,大部分都不会发送第三方的CookieNone...
HTTPOnly 属性HttpOnly属性指定该 Cookie 无法通过 JavaScript 脚本拿到,主要是document.cookie属性、XMLHttpRequest对象和 Request API 都拿不到该属性。这样就防止了该 Cookie 被脚本读到,只有浏览器发出 HTTP 请求时,才会带上该 Cookie。
JS 操作 Cookie
读取
document.cookie属性用于读写当前网页的 Cookie。
读取的时候,它会返回当前网页的所有非HTTPOnly Cookie,是一个;分隔的长字符串。
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 是一样的,一次只能设置一个。
document.cookie = 'test1=hello';document.cookie = 'test2=world';document.cookie// test1=hello;test2=world
写入 Cookie 的时候,可以同时写入 Cookie 的属性。
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';