浏览器基础知识-浏览器本地存储

0 阅读13分钟

浏览器端常用的存储技术及使用场景(重点)

浏览器端常用的存储技术是 CookieLocalStorageSessionStorage

(一)Cookie

Cookie 是最早被提出来的本地存储方式,在此之前,服务端是无法判断网络中的两个请求是否是同一用户发起的,为解决这个问题,Cookie 就出现了。

Cookie 是一种纯文本文件,每次发起 HTTP 请求都会携带 Cookie。

特性

  1. Cookie 一旦创建成功,名称就无法修改。
  2. Cookie 是无法跨域名的,也就是说 a 域名和 b 域名下的 Cookie 是无法共享的,这也是由 Cookie 的隐私安全性决定的,这样就能够阻止非法获取其他网站的 Cookie。
  3. 每个 Cookie 的大小限制在 4KB 左右,且由于 HTTP 请求头大小的限制,通常不建议存储超过几十个 Cookie。
  4. 有安全问题,如果 Cookie 未设置 HttpOnly,一旦页面存在 XSS 漏洞,攻击者就可以通过脚本读取 Cookie 并发送到自己的服务器,从而实现会话劫持。即使 Cookie 内容被加密(例如使用服务端加密的 Token),攻击者也可以原样转发该 Cookie 进行攻击,因此单纯依赖内容加密无法防御 XSS 窃取。正确做法是始终为认证相关的 Cookie 设置 HttpOnly,使其无法被 JavaScript 访问。
  5. Cookie 在请求一个新的页面的时候都会被发送过去。

在跨域域名之间共享 Cookie 的方法

  1. 使用 Nginx 反向代理:通过反向代理将不同域名的请求转发到同一域名下,从而实现 Cookie 共享。
  2. document.domain 方法:适用于子域名之间共享 Cookie,将不同子域名的 document.domain 设置为相同的主域名。
  3. postMessage 方法:适用于不同域名之间通过消息传递共享数据,结合 LocalStorage 实现跨域数据共享。
  4. 第三方 Cookie 配置:通过设置 SameSite=None 和 Secure 属性,允许第三方 Cookie 在跨域场景下使用。
  5. 服务端共享 session:在一个站点登录后,当浏览器访问其他站点时,由这些站点的服务端根据共享的 session 数据自行写入本域 Cookie。

使用场景

  1. 最常见的使用场景,就是 Cookie 和 session 结合使用,我们将 sessionId 存储到 Cookie 中,每次发请求都会携带这个 sessionId,这样服务端就知道是谁发起的请求,从而响应相应的信息。
  2. 统计页面的点击次数,网页端或者服务端将页面访问次数存入 Cookie。

(二)LocalStorage

LocalStorage 是 HTML5 新引入的特性,有时候我们存储的信息较大,Cookie 就不能满足我们的需求,这时候 LocalStorage 就派上用场了。

优点

  1. 在大小方面,LocalStorage 的大小一般为 5MB(不同浏览器可能有所不同,通常在 5MB 到 10MB 之间),可以储存更多的信息。
  2. LocalStorage 是持久储存,并不会随着页面的关闭而消失,除非主动清理,不然会永久存在。
  3. 仅储存在本地,不像 Cookie 那样每次 HTTP 请求都会被携带。

缺点

  1. 存在浏览器兼容问题,IE8 以下版本的浏览器不支持。
  2. 如果浏览器设置为隐私模式,那我们将无法读取到 LocalStorage。
  3. LocalStorage 受到同源策略的限制,即协议、主机地址、端口号三者必须完全一致,否则无法访问。
// 协议
http:、https:、ftp:、file:、ws:(WebSocket)、wss:(安全的 WebSocket// 主机地址
example.com
example.com 与它的实际IP地址(如 93.184.216.34)在浏览器的同源策略下被视为不同源,
因为同源策略比较的是主机地址的字符串表示,而不会尝试解析域名与IP地址的对应关系

// 端口
8080

使用场景

  1. 有些网站有换肤功能,这时候就可以将换肤的信息存储在本地的 LocalStorage 中,当需要换肤的时候,直接操作 LocalStorage 即可。
  2. 在网站中的用户浏览信息也会存储在 LocalStorage 中,还有网站的一些不常变动的个人信息等也可以存储在本地的 LocalStorage 中。
// 保存数据到 LocalStorage(可能需要 JSON.stringify)
localStorage.setItem('key', 'value');

// 从 LocalStorage 获取数据(可能需要 JSON.parse)
let data = localStorage.getItem('key');

// 从 LocalStorage 删除保存的数据
localStorage.removeItem('key');

// 从 LocalStorage 删除所有保存的数据
localStorage.clear();

// 获取某个索引的 Key(类似于数组的索引访问,提供顺序遍历能力)
localStorage.key(index)

(三)SessionStorage

SessionStorage 和 LocalStorage 都是在 HTML5 才提出来的存储方案。

SessionStorage 主要用于临时保存同一窗口(或标签页)的数据,刷新页面时不会删除,关闭窗口或标签页之后将会删除这些数据。

与 LocalStorage 对比

  1. 都在本地进行数据存储。
  2. SessionStorage 也有同源策略的限制,但是 SessionStorage 有一条更加严格的限制,SessionStorage 只有在同一个浏览器的同一个标签页下才能够共享(通过 window.open 或 a 标签打开的新页可能共享,取决于浏览器实现)。
  3. 都不能被传统爬虫爬取:传统爬虫只能获取服务器返回的静态 HTML 页面,无法执行 JS,因此无法读取存储在 LocalStorage 和 SessionStorage 中的数据。

使用场景

由于 SessionStorage 具有时效性,所以可以用来存储一些网站的游客登录的信息,还有临时的浏览记录的信息。当关闭网站之后,这些信息也就随之消除了。

// 保存数据到 sessionStorage(可能需要 JSON.stringify)
sessionStorage.setItem('key', 'value');

// 从 sessionStorage 获取数据(可能需要 JSON.parse)
let data = sessionStorage.getItem('key');

// 从 sessionStorage 删除保存的数据
sessionStorage.removeItem('key');

// 从 sessionStorage 删除所有保存的数据
sessionStorage.clear();

// 获取某个索引的Key(类似于数组的索引访问,提供顺序遍历能力)
sessionStorage.key(index)

Cookie 有哪些字段,作用分别是什么?(重点)

Cookie 由以下字段组成:

  1. Name:Cookie 的名称。

  2. Value:Cookie 的值,对于认证 Cookie,value 值包括 Web 服务器所提供的访问令牌。

  3. Size:Cookie 的大小。

  4. Domain:可以访问该 Cookie 的域名,Cookie 机制并未遵循严格的同源策略,允许一个子域可以设置或获取其父域的 Cookie。

    当需要实现单点登录方案时,Cookie 的上述特性非常有用,然而也增加了 Cookie 受攻击的危险,比如攻击者可以借此发动会话定置攻击。因而,浏览器禁止在 Domain 属性中设置 .org、.com 等通用顶级域名、以及在国家及地区顶级域下注册的二级域名,以减小攻击发生的范围。

  5. Path:可以访问此 Cookie 的页面路径。比如 Domain 是 abc.com,path 是 /test,那么只有 /test 路径下的页面可以读取此 Cookie。

  6. Secure:指定是否使用 HTTPS 安全协议发送 Cookie。

    使用 HTTPS 安全协议,可以保护 Cookie 在浏览器和 Web 服务器间的传输过程中不被窃取和篡改。

    该方法也可用于 Web 站点的身份鉴别,即在 HTTPS 的连接建立阶段,浏览器会检查 Web 网站的 SSL 证书的有效性。

    但是基于兼容性的原因(比如有些网站使用自签署的证书)在检测到 SSL 证书无效时,浏览器并不会立即终止用户的连接请求,而是显示安全风险信息,用户仍可以选择继续访问该站点。

  7. HttpOnly:该属性用来设置 Cookie 能否通过脚本来访问,默认为空,即可以通过脚本访问。

    在客户端是不能通过 JS 代码去设置一个 HttpOnly 类型的 Cookie 的,这种类型的 Cookie 只能通过服务端来设置

    该属性用于防止客户端脚本通过 document.cookie 属性访问 Cookie,有助于保护 Cookie 不被跨站脚本攻击窃取或篡改。

    但是,HttpOnly 的应用仍存在局限性。一些浏览器可以阻止客户端脚本对 Cookie 的读操作,但允许写操作;此外大多数浏览器仍允许通过 XMLHTTP 对象读取 HTTP 响应中的 Set-Cookie 头。

  8. SameSite:跨站携带策略,现代浏览器默认 Lax,有效防御 CSRF 攻击。

  9. Expires/Max-age:Cookie 的超时时间。若设置其值为一个时间,那么当到达此时间后,此 Cookie 失效。

    不设置的话默认值是 session,意思是 Cookie 会和 session 一起失效,当浏览器关闭(不是浏览器标签页,而是整个浏览器)后,此 Cookie 失效。

总结

服务器端可以使用 Set-Cookie 的响应头部来配置 Cookie 信息。

一条 Cookie 包括了 5 个属性值:Domain、Path、Secure、HttpOnly、Expires

  • Domain 是域名,Path 是路径,Domain 和 Path 一起限制了 Cookie 能够被哪些 url 访问。
  • Secure 规定了 Cookie 只能在确保安全(HTTPS)的情况下传输。
  • HttpOnly 规定了这个 Cookie 只能被服务器访问,不能使用 JS 脚本访问。
  • Expires 指定了 Cookie 失效的时间。

实践建议

  • 认证相关的 Cookie 必须同时设置 Secure、HttpOnly、SameSite=Lax(或 Strict)。
  • Cookie 单条大小限制约 4KB,单个域名下不宜超过 20~30 条(实际上总大小超限会导致请求头过大)。
  • 跨域共享 Cookie 需配合 SameSite=None; Secure,并确保服务端支持 CORS 且 withCredentials=true。

Cookie、SessionStorage、LocalStorage 的区别(重点)

Cookie

最开始是服务器端用于记录用户状态的一种方式,由服务器设置,在客户端存储,然后每次发起同源请求时,发送给服务器端。

Cookie 最多能存储 4KB 数据,它的生存时间由 Expires 属性指定,并且 Cookie 只能被同源的页面访问共享。

注意,“同源”在 Cookie 中有一个重要的例外——Domain 和 Path 属性,Cookie 允许设置 Domain 为父域名,从而实现子域之间的共享;Path 可以设置只有在某个路径及其子路径下的页面才会携带此 Cookie。Domain 放宽了同源限制(允许子域),Path 进一步限制了 URL 路径。而 LocalStorage 和 SessionStorage 严格遵循同源策略,即使是子域也无法共享父域的存储数据(除非使用 postMessage 等跨域通信手段)。

SessionStorage

HTML5 提供的一种浏览器本地存储的方法,它借鉴了服务器端 session 的概念,代表的是一次会话中所保存的数据。

它一般能够存储 5M 或者更大的数据,在当前窗口关闭后就失效了,并且只能被同一个窗口的同源页面所访问共享。

LocalStorage

HTML5 提供的一种浏览器本地存储的方法,它一般也能够存储 5M 或者更大的数据。

和 SessionStorage 不同的是,除非手动删除它,否则它不会失效,并且 LocalStorage 也只能被同源页面所访问共享。

前端的存储方式(重点)

Cookie

在 HTML5 标准前本地储存的主要方式,优点是兼容性好,请求头自带 Cookie 方便,缺点是大小只有 4KB,自动请求头加入 Cookie 浪费流量,每个域名限制 20 个 Cookie,使用起来麻烦,需要自行封装。

Cookie 优化:尽量减少 Cookie 的大小和数量,避免在不必要的请求中携带 Cookie。

Cookie 安全:设置 Secure,防止传输过程中的 Cookie 劫持(如中间人攻击);设置 HttpOnly 属性,防止 XSS 攻击导致的 Cookie 劫持。

LocalStorage

HTML5 加入的以键值对(Key-Value)为标准的方式,优点是操作方便,永久性储存(除非手动删除),大小为 5M,兼容 IE8+。

LocalStorage 优化:避免存储大量数据,定期清理不再需要的数据。

LocalStorage 安全:避免存储敏感信息,如用户密码、银行卡号等。

SessionStorage

与 LocalStorage 基本类似,区别是 SessionStorage 当页面关闭后会被清理,而且与 Cookie、LocalStorage 不同,它不能在所有同源窗口中共享,是会话级别的储存方式。

IndexedDB

是被正式纳入 HTML5 标准的数据库储存方案,它是 NoSQL 数据库,用键值对进行储存,可以进行快速读取操作,非常适合 Web 场景,同时用 JS 进行操作会非常方便。

IndexedDB 优化:合理使用事务和索引,提高数据读写性能。

IndexedDB 安全:对敏感数据进行加密存储,防止数据泄露。

Web SQL

2010 年被 W3C 废弃的本地数据库数据存储方案,但是主流浏览器(火狐除外)都已经有了相关的实现,Web SQL 类似于 SQLite,是真正意义上的关系型数据库,用 SQL 进行操作,当我们用 JS 时要进行转换,较为繁琐。

虽然目前主流浏览器(除 Firefox 外)仍支持,但 W3C 已停止维护,新项目严禁使用,应该使用 IndexedDB。

浏览器本地存储技术总结

小型数据存储方案

  • Cookie:适用于需要在客户端和服务器之间传递的少量数据(≤4KB)
  • LocalStorage:适用于长期保存的非敏感数据(≤5MB)
  • SessionStorage:适用于临时存储会话期间的数据(≤5MB)

大型数据存储方案

  • IndexedDB:适用于存储大量结构化数据(≥250MB),支持事务、索引和查询

IndexedDB 的特点

键值对储存

IndexedDB 内部采用对象仓库(object store)存放数据。所有类型的数据都可以直接存入,包括 JS 对象。对象仓库中,数据以“键值对”的形式保存,每一个数据记录都有对应的主键,主键是独一无二的,不能有重复,否则会抛出一个错误。

异步

IndexedDB 操作时不会锁死浏览器,用户依然可以进行其他操作,这与 LocalStorage 形成对比,后者的操作是同步的。异步设计是为了防止大量数据的读写,拖慢网页的表现。

支持事务

IndexedDB 支持事务(transaction),这意味着一系列操作步骤之中,只要有一步失败,整个事务就都取消,数据库回滚到事务发生之前的状态,不存在只改写一部分数据的情况。

同源限制

IndexedDB 受到同源限制,每一个数据库对应创建它的域名。网页只能访问自身域名下的数据库,而不能访问跨域的数据库。

储存空间大

IndexedDB 的储存空间比 LocalStorage 大得多,一般来说不少于 250MB,甚至没有上限。

支持二进制储存

IndexedDB 不仅可以储存字符串,还可以储存二进制数据(ArrayBuffer 对象和 Blob 对象)。

总结

本文详细介绍了浏览器本地存储的几种主要方式,包括 Cookie、LocalStorage、SessionStorage 以及 IndexedDB。每种存储方式都有其独特的特点、适用场景和限制。

  • Cookie 适用于需要在客户端和服务器之间传递的少量数据,如会话管理和用户跟踪。
  • LocalStorage 适合存储需要长期保存的非敏感数据,如用户偏好设置和应用状态。
  • SessionStorage 适用于临时存储会话期间的数据,如表单输入和临时状态。
  • IndexedDB 则为大量结构化数据提供了高效的存储和检索能力,适合离线应用和复杂数据管理。

选择合适的存储方式取决于具体的应用场景和需求,开发者需要根据数据的大小、生命周期、安全性和访问模式来做出明智的选择。