很多人知道 Web Storage,但是你清楚 Cookie 嘛
次访问
可以在浏览器的 Application
面板下看到浏览器的本地存储包含了:Cookie
、sessionStorage
、localStorage
和 IndexedDB
。
Cookie
Cookie 是什么
Cookie
又叫 HTTP Cookie
或者叫浏览器 Cookie
。Cookie
的作用是维护服务端和客户端的会话状态,简而言之就是告诉服务器当前客户端用户的一些信息,比如是否登录啥的。
Cookie 是如何工作的
Cookie
通常是由服务端生成,然后通过响应头的 Set-Cookie
发送给客户端浏览器:
1 | HTTP/1.0 200 OK |
浏览器会将 Cookie
保存在本地,并且会在下次请求头部的 Cookie
中附上这个值:
GET /home.html HTTP/1.1
Host: www.example.org
Cookie: my_cookie=bulandent
Cookie 分类
按照 Cookie
的生命周期可以将它分为两类:
- 会话
Cookie
:没有指定过期时间 (Expires
)或有效期(Max-Age
)的Cookie
,当浏览器关闭后会被自动删除,但是现在很多浏览器都实现了会话恢复功能,即使浏览器关闭,会话Cookie
也会被保留下来;这种类型的Cookie
会保存在浏览器的内存中; - 持久性
Cookie
:通过指定过期时间 (Expires
)或有效期(Max-Age
)的一种Cookie
,存储于客户端硬盘中。设定的日期和时间是指和客户端系统时间进行比较的。
Cookie 限制
Cookie
会绑定特定的域名(Domain
),除此之外,它还有如下一些限制:
通常,只要遵守以下大致的限制,就不会在任何浏览器中碰到问题:
- 不超过 300 个
Cookie
; - 每个
Cookie
不超过 4KB; - 每个域名下不超过 20 个
Cookie
。
每个域能设置的 Cookie
总数也是受限的,但不同浏览器的限制不同。例如:
- 最新版 IE 和 Edge 限制每个域不超过 50 个
Cookie
; - 最新版 Firefox 限制每个域不超过 150 个
Cookie
; - 最新版 Opera 限制每个域不超过 180 个
Cookie
; - Safari 和 Chrome 对每个域的
Cookie
数没有硬性限制。
如果 Cookie
总数超过了单域名的上限,浏览器就会删除之前设置的 Cookie
,而删除的逻辑不同浏览器也不大相同。
Cookie 构成
Cookie
构成除了以上提到的 Name
、Value
、Domain
、Expires/Max-Age
外,还有几个比较重要的需要说下:
Path
:请求URL
中包含这个路径才会把Cookie
发送到服务器;Secure
:只有HTTPS
请求才会发送标记为Secure
的Cookie
;HttpOnly
:将限制在客户端通过document.cookie
读取设置为HttpOnly
的Cookie
;SameSite
:控制Cookie
在跨站请求的时候是否会被发送,有 3 个值:None
允许跨站请求发送;Lax
:允许跨站GET
请求发送;Strict
:不允许跨站请求发送;
除了服务器能够设置 Cookie 外,客户端也可以通过 document.cookie 设置。
Cookie 缺陷
Cookie
会被附加在每个HTTP
请求中,所以无形中增加了流量;- 由于在
HTTP
请求中的Cookie
是明文传递的,所以安全性成问题,除非用超文本传输安全协定; Cookie
的大小限制在4KB
左右,对于复杂的存储需求来说是不够用的。
Cookie 安全
黑客常常会利用 Cookie
进行攻击,比如 XSS
和 CSRF
等;所以为了网站安全,通常需要针对 Cookie
做一些安全措施:
- 对特殊的
Cookie
设置HttpOnly
,防止被客户端脚本读取,比如维护登录状态的Cookie
就可以这么做; - 用于敏感信息(例如指示身份验证)的
Cookie
的生存期应较短,并且SameSite
属性设置为Strict
或Lax
。
Web Storage
Web Storage
存在的目的就是为了解决每次向服务器请求的时候都需要携带 Cookie
信息的问题。Web Storage
包含了 2 个对象:sessionStorage
和 localStorage
。通过这 2 个对象实现了:
- 提供在
Cookie
之外的存储会话数据的途径; - 提供跨会话持久化存储大量数据的机制。
Web Storage 的限制
和其他客户端数据存储方案一样,Web Storage
也有限制。
- 存储大小:不同浏览器给
sessionStorage
和localStorage
设置了不同的空间限制,但大多数会限制为每个源 5MB; - 存储类型:只能存储字符串,所以如果数据是对象结构的,需要通过
JSON.stringify
先转成字符串; - 存储限制于同一个源(
origin
),这也是同源策略的限制之一。即http://a.com
和https://a.com
存储的 ``Web Storage` 数据是不相同的。
Web Storage
提供了一套详细的 API
使得我们可以很好的进行数据存储:
属性
Storage.length
:返回一个整数,表示存储在 Storage 对象中的数据项数量。
方法
Storage.key(n)
:该方法接受一个数值 n 作为参数,并返回存储中的第 n 个键名;Storage.getItem()
:该方法接受一个键名作为参数,返回键名对应的值;Storage.setItem()
:该方法接受一个键名和值作为参数,将会把键值对添加到存储中,如果键名存在,则更新其对应的值;Storage.removeItem()
:该方法接受一个键名作为参数,并把该键名从存储中删除;Storage.clear()
:调用该方法会清空存储中的所有键名。
sessionStorage
和 localStorage
都是 Storage
的实例,所以自然而然的它们都拥有上面的属性和方法。
sessionStorage
sessionStorage
对象只会存储会话数据,这意味着当浏览器 tab 页被关闭的时候,对应的 sessionStorage
数据将被清除。除此之外,它还有如下表现:
- 不受页面刷新(包括强制刷新)影响,并且可以在浏览器崩溃并重启后恢复;
- 在当前页面通过新标签页或窗口打开一个新页面的时候,新页面会复制父级页面的
sessionStorage
数据; - 使用同一个
URL
打开多个标签页,它们各自的sessionStorage
数据不同;
localStorage
区别于 sessionStorage
,localStorage
的存储不受会话限制而且能够长期存储于客户端浏览器中,直到手动删除或者清除浏览器缓存。
IndexedDB
虽然 Web Storage
在存储较少量的数据很有用,但对于存储更大量的结构化数据来说力不从心,这个时候就需要用到 IndexedDB
,它类似于 MySQL
,但是和传统数据库最大的区别在于,它是适用对象存储而不是表格保存数据。IndexedDB
也受到源的限制。
和 Web Storage 的区别
- 存储大小:
Web Storage
限制每个源大约 5MB。IndexedDB
的存储空间有 2 个限制:全局限制即为浏览器的最大存储空间一般是可用磁盘空间的 50%;组限制为全局限制的 20%,且它至少有 10MB,最大为 2GB 存储空间; - 存储类型:
Web Storage
只能存储字符串,IndexedDB
可以存储字符串、Blob
和ArrayBuffer
; Web Storage
的存储操作是同步进行的;IndexedDB
由于数据量大,所以多数操作都是异步执行的;