# 浏览器存储
存储方式:
- cookie
- webStorage(localStorage和sessionStorage)
- indexedDB
# Cookie
# 目的
Cookie诞生之初的作用就是解决HTTP的无状态请求,用来记录一些用户相关的一些状态。
- 会话状态管理(如用户登录状态、购物车、游戏分数或其它需要记录的信息)
- 个性化设置(如用户自定义设置、主题等)
- 浏览器行为跟踪(如跟踪分析用户行为等)
Cookie 本质上就是浏览器里面存储的一个很小的文本文件,内部以键值对的方式来存储(在chrome开发者面板的Application这一栏可以看到)。向同一个域名下发送请求,都会携带相同的 Cookie,服务器拿到 Cookie 进行解析,便能拿到客户端的状态。
# 缺点
h5之前,存储主要用cookies,缺点:
- 容量缺陷。大小限制4k。
- 性能缺陷。请求头上带着数据,导致流量增加。Cookie 紧跟域名,不管域名下面的某一个地址需不需要这个 Cookie ,请求都会携带上完整的 Cookie,这样随着请求数的增多,其实会造成巨大的性能浪费的,因为请求携带了很多不必要的内容。
- 安全缺陷。由于 Cookie 以纯文本的形式在浏览器和服务器中传递,很容易被非法用户截获,然后进行一系列的篡改,在 Cookie 的有效期内重新发送给服务器,这是相当危险的。另外,在HttpOnly为 false 的情况下,Cookie 信息能直接通过 JS 脚本来读取。
- 操作缺陷。Cookie的原生api不友好,需要自行封装
# 参数
参数 | 说明 |
---|---|
key | cookie key |
value | cookie value |
expires | 过期时间。一旦过期浏览器自动删除cookie。删除:可以设置一个过去的时间;如果不设置过期时间,则cookie有效期是会话期间。 |
path | 路径。在指定路径的时候,凡是来自同一服务器,URL里有相同路径的所有WEB页面都可以共享cookies。 |
domain | 主机名,是指同一个域下的不同主机,例如:www.baidu.com和map.baidu.com就是两个不同的主机名。默认情况下,一个主机中创建的cookie在另一个主机下是不能被访问的,但可以通过domain参数来实现对其的控制:document.cookie = "name=value;domain=.baidu.com" 这样,所有*.baidu.com的主机都可以访问该cookie。 |
secure | 当 secure 属性设置为 true 时,cookie 只有在 https 协议下才能上传到服务器,而在 http 协议下是没法上传的,所以也不会被窃听。 |
httponly | 用于防止客户端脚本通过 document.cookie 属性访问 Cookie,有助于保护 Cookie 不被跨站脚本攻击窃取或篡改。但是,HTTPOnly 的应用仍存在局限性,一些浏览器可以阻止客户端脚本对 Cookie 的读操作,但允许写操作;此外大多数浏览器仍允许通过 XMLHTTP 对象读取 HTTP 响应中的 Set-Cookie 头。 |
# webStorage
HTML5 提供了两种在客户端存储数据的新方法:localStorage 和 sessionStorage,挂载在 window 对象下。 webStorage 是本地存储,数据不是由服务器请求传递的。从而它可以存储大量的数据,而不影响网站的性能。
# 目的
Web Storage的目的是为了克服由cookie带来的一些限制,当数据需要被严格控制在客户端上时,无须持续地将数据发回服务器。比如客户端需要保存的一些用户行为或数据,或从接口获取的一些短期内不会更新的数据,都可以利用Web Storage来存储。
# localStorage
以键值对(Key-Value)的方式存储,永久存储,永不失效,除非手动删除。IE8+支持,每个域名限制5M 打开同域的新页面也能访问得到。可以存储数组、数字、对象等可以被序列化为字符串的内容
window.localStorage.username = 'hehe' // 设置
window.localStorage.setItem('username', 'hehe') // 设置
window.localStorage.getItem('username') // 读取
window.localStorage.removeItem('username') // 删除
window.localStorage.key(1) // 读取索引为1的值
window.localStorage.clear()
2
3
4
5
6
# sessionStorage
sessionStorage 在关闭页面后即被清空,而 localStorage 则会一直保存。很多时候数据只需要在用户浏览一组页面期间使用,关闭窗口后数据就可以丢弃了,这种情况使用 sessionStorage 就比较方便。 注意,刷新页面 sessionStorage 不会清除,但是打开同域新页面访问不到。
window.sessionStorage.username = 'hehe' // 设置
window.sessionStorage.setItem('username', 'hehe') // 设置
window.sessionStorage.getItem('username') // 读取
window.sessionStorage.removeItem('username') // 删除
window.sessionStorage.key(1) // 读取索引为1的值
window.sessionStorage.clear()
2
3
4
5
6
# indexedDB
IndexedDB 是一种底层 API,用于在客户端存储大量的结构化数据(也包括文件/二进制大型对象(blobs))。该 API 使用索引实现对数据的高性能搜索。虽然 Web Storage 在存储较少量的数据很有用,但对于存储更大量的结构化数据来说力不从心。而 IndexedDB 提供了这种场景的解决方案。
indexedDB 就是一个非关系型数据库,它不需要你去写一些特定的 sql 语句来对数据库进行操作,因为它是 nosql 的,数据形式使用的是 json。IndexedDB 很适合存储大量数据,它的 API 是异步调用的。
# 特点
- IndexedDB 是一种低级 API,用于客户端存储大量结构化数据。该 API 使用索引来实现对该数据的高性能搜索。
- 为应用创建离线版本。
# 操作方式
- 打开数据库并且开启一个事务。
- 创建一个 object store。
- 构建一个请求来执行一些数据库操作,像增加或提取数据等。
- 通过监听正确类型的 DOM 事件以等待操作完成。
- 在操作结果上进行一些操作(可以在 request 对象中找到)
# 基础 API
- 建立打开indexedDB:window.indexedDB.open("testDB")
- 关闭indexedDB:indexdb.close();
- 删除indexedDB:window.indexedDB.deleteDatabase(indexdb)。
注意
- 键值对存储。内部采用对象仓库存放数据,在这个对象仓库中数据采用键值对的方式来存储。
- 异步操作。数据库的读写属于 I/O 操作, 浏览器中对异步 I/O 提供了支持。
- 受同源策略限制,即无法访问跨域的数据库。
具体查看
indexedDB MDN (opens new window)
indexedDB 操作 (opens new window)
# 存储方式对比
cookie | localStorage | sessionStorage | IndexedDB | Web SQL | |
---|---|---|---|---|---|
规范 | HTTP规范 | HTML5规范 | HTML5规范 | HTML5规范 | 已被W3C规范废弃,但浏览器广泛支持 |
挂载对象 | DOM | BOM | BOM | BOM | BOM |
传输 | cookie数据始终在同源的http请求中携带(即使不需要)仅在本地保存,不会传输 | 仅在本地保存,不会传输 | 仅在本地保存,不会传输 | 仅在本地保存,不会传输 | |
存储大小 | 4k | 5M左右,各浏览器的存储空间有差异 | 5M左右,各浏览器的存储空间有差异 | ||
有效期 | 在设置的cookie过期时间之前一直有效,可以设置过期时间,也可以设置为会话级别的(浏览器关闭时过期) | 始终有效,窗口或浏览器关闭也一直保存 | 仅在当前浏览器窗口关闭前有效 | 始终有效,窗口或浏览器关闭也一直保存 | 始终有效,窗口或浏览器关闭也一直保存 |
作用域 | 属于服务器端,每次请求都会自动发送到服务器,适用于需要在服务器端读取的场景;所有同源窗口中都是共享的;设置 domain 后子域也共享 | 所有同源窗口中都是共享的 | 数据只在页面会话期间有效,关闭标签页或窗口后数据被清除;即使多个标签页访问的是同一域名下的同一页面,它们也无法共享 sessionStorage 数据 | 所有同源窗口中都是共享的 | 所有同源窗口中都是共享的 |
安全性 | 可以设置为 HttpOnly,防止 XSS 攻击;常用于存储会话信息,如用户登录状态 | 存储在客户端,容易受到 XSS 攻击;适用于存储不敏感的大量数据 | 存储在客户端,容易受到 XSS 攻击;适用于存储临时数据,如表单数据 | 存储在客户端,容易受到 XSS 攻击;适用于存储大量结构化数据,如数据库应用 |
# 存储方式跨域
cookie、localStorage 、sessionStorage 和 indexedDB 都是客户端存储技术,但它们在跨域访问方面有所不同:
- Cookie
- Cookie 是可以跨域的,但需要服务器在设置 Cookie 时指定
domain
属性,并且 Path 属性通常设置为/
。这样,同一域名下的所有子域都可以访问该 Cookie。 - 为了实现跨域 Cookie 共享,服务器需要设置
Access-Control-Allow-Credentials
为 true,并且Access-Control-Allow-Origin
不能使用*
,必须指定具体的域名。同时,客户端请求时需要携带credentials: 'include'
或者在 XMLHttpRequest 中设置withCredentials = true
;
- Cookie 是可以跨域的,但需要服务器在设置 Cookie 时指定
- localStorage 、sessionStorage 和 indexedDB
- 根据同源策略,localStorage 、sessionStorage 和 indexedDB 默认情况下不能被跨域访问。它们只能被同一域名、协议和端口下的页面访问。
- 但是,可以通过以下几种方法实现跨域访问:
- 使用 iframe 嵌套:在一个页面中嵌入另一个页面的 iframe,并将其 src 属性设置为存储数据的页面所在的域名下的页面地址。然后,可以通过 iframe 的 contentWindow 访问存储在另一个域名下的数据。
- 使用代理页面:创建一个代理页面,该页面与目标域名具有相同的域,并通过这个代理页面来操作 localStorage 或 sessionStorage。
- 跨域资源共享(CORS):这是一种现代的跨域技术,可以让前端直接跨域访问 localStorage 或 sessionStorage 中的数据。不过,这需要后端配置适当的 HTTP 头部,以允许跨域访问。
- 使用 postMessage API:这是一种浏览器提供的 API,用于在不同窗口或跨域的 iframe 之间进行安全的消息传递。可以在不同域名的页面中使用 postMessage 将数据从一个窗口传递到另一个窗口,并在目标窗口中将数据存储到 localStorage 或 sessionStorage 中