既然有了 cookie 为什么还要 localStorage?

Web Storage

Web Storage 的目的是解决通过客户端存储不需要频繁发送回服务器的数据时使用 cookie 的问题。
Web Storage 主要有两个目标:

  1. 提供在 cookie 之外的存储会话数据的途径;
  2. 提供跨会话持久化存储大量数据的机制;

Web Storage 定义了两个对象: localStorage 和 sessionStorage。前者是永久存储机制,而后者是跨会话的存储机制。这两个浏览器存储 API 提供了在浏览器中不收页面刷新影响而存储数据的两种方式。

Storage 类型

Storage 类型用于保存 名/值 对数据,直至存储空间上限(由浏览器决定)。Storage 的实例与其他对象一样,但增加了以下方法:

  1. clear(): 删除所有值;
  2. getItem(name): 取得给定 name 值;
  3. key(index): 取得给定数值位置的名称;
  4. removeItem(name): 删除给定 name 的 名/值 对;
  5. setItem(name,value): 设置给定 name 的值;

getItem()、removeItem(name) 和 setItem() 方法可以直接或间接通过 Storage 对象调用。因为每个数据项都作为属性存储在该对象上,所以可以使用点或括号操作符访问这些属性,统统同样的操作来设置值,也可以使用 delete 操作符来删除属性。

localStorage 对象

在修订的 HTML5 规范里,localStorage 对象取代了 globalStorage,作为在客户端持久存储数据的机制,要访问同一个 localStorage 对象,页面必须来自同一个域(子域不可以)、在想用的端口上使用相同的协议。
因为 localStorage 是 Storage 的实例,所以可以像使用 sessionStorage 一样使用 localStorage。具体示例:

// 使用方法存储数据
localStorage.setItem("moment", 777);

// 使用属性存储数据
localStorage.nickname = "moment";

// 使用方法获取数据
const name = localStorage.getItem("moment");

// 使用属性获得数据
const nickname = localStorage.nickname;

两种存储方法的区别在于,存储在 localStorage 中的数据会保留到通过 JavaScript 删除或者用户清除浏览器缓存。localStorage 数据不受页面刷新影响,也不会因关闭窗口,标签也或重新启动浏览器而丢失。

存储事件

每当 Storage 对象发生变化时,都会在文档上触发 storage 事件,使用属性或者 setItem() 设置值、使用 delete 或 removeItem() 删除值,以及每次调用 clean() 时都会触发这个事件,这个事件的事件对象有如下四个属性:

  1. domain: 存储变化对应的域;
  2. key: 被设置或删除的键;
  3. newValue: 键被设置的新值,若键被删除则为 null;
  4. oldValue: 键变化之前的值。

可以使用如下代码监听 storage 事件:

window.addEventListener("storage", function (e) {
  document.querySelector(".my-key").textContent = e.key;
});

对于 sessionStorage 和 localStorage 上的任何更改都会触发 storage 事件,但 storage 事件不会区分这两者。

通过后端返回来的 token 为什么是存储在 localStorage 而不是存储在 cookie 中?

  1. 前后端分离架构: 在一些现代的 Web 应用程序中,前端和后端通常是通过 API 进行通信的,而不是使用传统的服务器端渲染。在这种情况下,前端可能是一个独立的应用程序,如基于 JavaScript 的单页应用或移动应用程序。由于前端和后端是分离的,Cookie 在这种架构中不太容易管理,因为跨域请求可能会遇到一些限制。localStorage 提供了一种更方便的解决方案,前端应用程序可以直接访问和管理存储在本地的令牌;
  2. 安全性需求: 在某些情况下,开发者可能认为将令牌存储在 Cookie 中存在一些安全风险,尤其是在面对跨站脚本攻击 XSS 和请求伪造 CSRF 时,可以采取适当的安全措施,例如使用 HttpOnly 和 Secure 标志,以减少潜在的安全问题。使用 localStorage 可以减少某些安全风险,因为 LocalStorage 中的数据不会自动发送到服务器,且可以通过一些安全措施(如加密)来增强数据的安全性;
  3. 令牌过期处理: Cookie 可以具有过期时间,可以在设置失效时间后自动删除,这有助于确保 Token 的安全性和有效性。使用 localStorage 存储令牌可以让令牌在浏览器关闭后仍然保持有效,这在某些应用场景下是有用的。例如,用户可能关闭了浏览器,然后再次打开时仍然保持登录状态,而不需要重新输入凭据;

注意:使用 localStorage 存储 token 也不是说百分百安全的,依然会存在一些问题和风险,如容易收到 XSS 攻击、不支持跨域共享等。因此,在使用 localStorage 存储令牌时,开发者需要采取适当的安全措施,如加密存储数据、定期更新令牌等,以确保令牌的安全性和有效性。

localStorage 如何实现跨域

localStorage 是一直域限制的存储机制,通常只能在同一域名下的页面中访问。默认情况下,localStorage 的数据在不同域名或跨域的情况下是无法直接访问的。有几种方法可以实现跨域访问 localStorage 中的数据:

  1. 域名映射(Domain Mapping): 将不同域名都指向同一个服务器 IP 地址。这样不同域名下的页面就可以共享同一个 localStorage 中的数据;
  2. postMessage API: postMessage 是一种浏览器提供的 API,用于在不同窗口或跨域的 iframe 之间进行安全的消息传递。你可以在不同域名的页面中使用 postMessage 将数据从一个窗口传递到另一个窗口,并在目标窗口中将数据存储到 localStorage 中;

使用 postMessage 将数据从一个窗口传递到另一个窗口,并在目标窗口中将数据存储到 localStorage 中,实例代码如下:

// 发送消息到目标窗口
window.postMessage(
  { key: "token", value: "1233211234567" },
  "https://liangzai.com"
);

在接收消息的窗口中:

// 监听消息事件
window.addEventListener("message", function (event) {
  if (event.origin === "https://sourcedomain.com") {
    // 存储数据到 LocalStorage
    localStorage.setItem(event.data.key, event.data.value);
  }
});

cookie 和 localStorage 的区别

Cookie 和 LocalStorage 是两种用于在浏览器中存储数据的机制,它们在以下方面有一些区别:

  1. 存储容量: Cookie 的存储容量通常较小,每个 Cookie 的大小限制在几 KB 左右。而 LocalStorage 的存储容量通常较大,一般限制在几 MB 左右。因此,如果需要存储大量数据,LocalStorage 通常更适合;
  2. 数据发送: Cookie 在每次 HTTP 请求中都会自动发送到服务器,这使得 Cookie 适合用于在客户端和服务器之间传递数据。而 localStorage 的数据不会自动发送到服务器,它仅在浏览器端存储数据,因此 LocalStorage 适合用于在同一域名下的不同页面之间共享数据;
  3. 生命周期:Cookie 可以设置一个过期时间,使得数据在指定时间后自动过期。而 LocalStorage 的数据将永久存储在浏览器中,除非通过 JavaScript 代码手动删除;
  4. 安全性:Cookie 的安全性较低,因为 Cookie 在每次 HTTP 请求中都会自动发送到服务器,存在被窃取或篡改的风险。而 LocalStorage 的数据仅在浏览器端存储,不会自动发送到服务器,相对而言更安全一些;

总结

Cookie 适合用于在客户端和服务器之间传递数据、跨域访问和设置过期时间,而 LocalStorage 适合用于在同一域名下的不同页面之间共享数据、存储大量数据和永久存储数据。选择使用哪种机制应根据具体的需求和使用场景来决定。

你可能感兴趣的:(前端)