Web Cookie (或也叫Http Cookie、浏览器Cookie)是服务器发送到客户端浏览器并保存本地上的一小块数据。它会在浏览器下次向同一服务器再发起请求时被携带并发送到服务器上。
通常Cookie用来告知服务端两个请求是否来自于同一浏览器,如保持用户登录状态。Cookie使基于无状态的Http协议记录稳定的状态信息称为可能。
Cookie主要用于三个方面:
- 回话状态管理(比如用户登录状态,购物车等)
- 个性化设置(比如用户自定义的主题等)
- 浏览器行为跟踪(跟踪分析用户行为等)
Cookie曾经主要用于客户端数据的存储,但随着时代的发展,现代浏览器支持各种各样的存储方式,Cookie逐渐被淘汰。由于服务器指定Cookie后,浏览器的每次请求都会携带Cookie数据,会带来额外的性能开销(尤其是在移动环境下)。新的浏览器Api比如StorageApi和IndexedDB可以直接将数据存在本地。
Cookie的创建
服务端或客户端都可以创建Cookie。
服务端创建Cookie
当服务器收到Http请求时,服务器可以在响应头里面添加Set-Cookie
选项。浏览器收到响应后会根据响应体中的Set-Cookie
字段的值保存Cookie。
之后对该服务器的每次请求都会在请求头中的Cookie
字段将Cookie发送给服务器。
会话期Cookie
会话期Cookie是最简单的Cookie,浏览器关闭后就会自动删除。仅仅在会话期有效。
会话期Cookie不需要指指定过期时间(Expires)或者有效期(Max-Age)。但是有些游览器提供了会话恢复功能,这种情况下即使关闭了浏览器,会话期Cookie也会保留,就好像浏览器没有关闭一样。
持久Cookie
持久Cookie可以指定一个特定的过期时间(Expires)或者有效期(Max-Age)。
例如:
1 | Set-Cookie: JSESSIONID=xxxx; Expires=Wed May 27 2020 16:08:42 GMT |
但这个时间和服务器没关系,只和客户端浏览器有关。
Secure 和 HttpOnly 标记
标记为Secure
的Cookie值应通过被Https协议加密过的请求发送给服务端。即便设置了Secure
,敏感信息也不应该通过Cookie传递,因为Cookie有其固有的不安全性。Secure
也无法提供确实的安全保障。
为避免跨域脚本(XSS)攻击,通过JavaScript的Document.cookie
Api无法访问带有HttpOnly
标记的Cookie。它们只应该发送给服务端。
PS:这里要说一句,W3C的标准中做了限制,规定客户端无法获取请求响应体中的Set-Cookie
字段,无论是跨域还是同域。
Cookie 的作用域
Domain
和Path
标识定义了Cookie的作用域。
Domain
标识指定了哪些主机可以接受Cookie。如果不指定,默认为当前主机(不包含子域名),如果指定了Domain
,则一般包含子域名。
Path
标识指定了主机下的哪些路径可以接受Cookie(该url必须存在于请求url中)。以字符/
作为路径分隔符,子路径也会被匹配。
SameSite Cookies
SameSite
Cookie允许服务器要求某个Cookie在跨站请求时不会发送。从而可以阻止跨站请求伪造攻击(CSRf)。
有三个值:
None
浏览器会在同站、跨站请求下继续发送cookies,不区分大小写。Strict
只在访问相同站点时发送cookies。Lax
为默认选项。cookies将会为一些跨站子请求保留。如图片的加载或者frames的调用。
客户端浏览器创建Cookie
通过Document.cookie
属性可以创建新的Cookie。也可以通过该属性访问非HttpOnly
标记的Cookie。
例如:
1 | document.cookie = 'id=3'; |
也可以直接去开发者工具面板里面的Application -> Cookies
里面创建。
Cookie的增删改查
新增个Cookie
前面说了用客户端浏览器创建Cookie的方式,可以用Document.cookie
创建,也可以用浏览器的开发者工具面板可视化创建。
新增的时候是单个Cookie新增,
修改Cookie
修改Cookie是通过Document.cookie
直接重新赋值即可。但需要注意的是,这个修改的Cookie的其他参数(Path/Domain等)需要都一样,不然会认为是新增了一个Cookie。
查看Cookie
直接Document.cookie
就可以展示可访问的Cookie。
删除Cookie
重新赋值即可,只需要将这个新Cookie的expires
选项设置为过去的一个时间即可。但需要注意得失,path/domain
这些选项需要和旧的cookie一致,否则会认为是新增。