面试官: 既然有了 cookie 为什么还要 localStorage?😕😕😕
Web Storage
Web Storage
最终是网页超文本应用技术工作组在 Web Applications 1.0
规范中提出的。这个规范中的草案最终成为了 HTML5
的一部分,后来有独立称为自己的规范。Web Storage
的目的是解决通过客户端存储不需要频繁发送回服务器的数据时使用 cookie
的问题。
Web Storage
规范最新的版本是第 2 版,这一版规范主要有两个目标:
- 提供在
cookie
之外的存储会话数据的途径; - 提供跨会话持久化存储大量数据的机制;
Web Storage
定义了两个对象: localStorage
和 sessionStorage
。前者是永久存储机制,而后者是跨会话的存储机制。这两个浏览器存储 API
提供了在浏览器中不收页面刷新影响而存储数据的两种方式。
Storage 类型
Storage
类型用于保存 名/值
对数据,直至存储空间上限(由浏览器决定)。Storage
的实例与其他对象一样,但增加了以下方法:
clear()
: 删除所有值;getItem(name)
: 取得给定name
值;key(index)
: 取得给定数值位置的名称;removeItem(name)
: 删除给定name
的名/值
对;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()
时都会触发这个事件,这个事件的事件对象有如下四个属性:
domain
: 存储变化对应的域;key
: 被设置或删除的键;newValue
: 键被设置的新值,若键被删除则为null
;oldValue
: 键变化之前的值。
我们可以使用如下代码监听 storage
事件:
window.addEventListener("storage", function (e) {
document.querySelector(".my-key").textContent = e.key;
});
对于 sessionStorage
和 localStorage
上的任何更改都会触发 storage
事件,但 storage
事件不会区分这两者。
这是一道面试题
在不久前,被问到这样一个问题,我们通过后端返回来的 token
为什么是存储在 localStorage
而不是存储在 cookie
中?
考虑这个问题的首先我们应该知道,token
就是一个字符串,而使用 cookie
的话,大小是满足的,所以考察的点就不在这个内存上面了。
之所以使用 localStorage
存储 token
,而不是使用 cookie
,这可能基于以下几个方面考虑:
- 前后端分离架构: 在一些现代的
Web
应用程序中,前端和后端通常是通过API
进行通信的,而不是使用传统的服务器端渲染。在这种情况下,前端可能是一个独立的应用程序,如基于JavaScript
的单页应用或移动应用程序。由于前端和后端是分离的,Cookie
在这种架构中不太容易管理,因为跨域请求可能会遇到一些限制。localStorage
提供了一种更方便的解决方案,前端应用程序可以直接访问和管理存储在本地的令牌; - 安全性需求: 在某些情况下,开发者可能认为将令牌存储在
Cookie
中存在一些安全风险,尤其是在面对跨站脚本攻击XSS
时。使用localStorage
可以减少某些安全风险,因为LocalStorage
中的数据不会自动发送到服务器,且可以通过一些安全措施(如加密)来增强数据的安全性; - 令牌过期处理: 使用
localStorage
存储令牌可以让令牌在浏览器关闭后仍然保持有效,这在某些应用场景下是有用的。例如,用户可能关闭了浏览器,然后再次打开时仍然保持登录状态,而不需要重新输入凭据;
值得注意的是,使用 localStorage
存储 token
也不是说百分百安全的,依然会存在一些问题和风险,如容易收到 XSS
攻击、不支持跨域贡献等。因此,在使用 localStorage
存储令牌时,开发者需要采取适当的安全措施,如加密存储数据、定期更新令牌等,以确保令牌的安全性和有效性。
localStorage 如何实现跨域
localStorage
是一直域限制的存储机制,通常只能在同一域名下的页面中访问。这意味着默认情况下,localStorage
的数据在不同域名或跨域的情况下是无法直接访问的。然而,有几种方法可以实现跨域访问 localStorage
中的数据:
- 域名映射(
Domain Mapping
): 将不同域名都指向同一个服务器 IP 地址。这样不同域名下的页面就可以共享同一个localStorage
中的数据; 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);
}
});
这些方法提供了一些途径来实现跨域访问 localStorage
中的数据。具体选择哪种方法取决于你的需求和应用场景,以及你对目标域名的控制程度。需要注意的是,安全性是非常重要。
cookie 和 localStorage 的区别
Cookie
和 LocalStorage
是两种用于在浏览器中存储数据的机制,它们在以下方面有一些区别:
- 存储容量:
Cookie
的存储容量通常较小,每个Cookie
的大小限制在几KB
左右。而LocalStorage
的存储容量通常较大,一般限制在几MB
左右。因此,如果需要存储大量数据,LocalStorage
通常更适合; - 数据发送:
Cookie
在每次HTTP
请求中都会自动发送到服务器,这使得Cookie
适合用于在客户端和服务器之间传递数据。而localStorage
的数据不会自动发送到服务器,它仅在浏览器端存储数据,因此LocalStorage
适合用于在同一域名下的不同页面之间共享数据; - 生命周期:
Cookie
可以设置一个过期时间,使得数据在指定时间后自动过期。而LocalStorage
的数据将永久存储在浏览器中,除非通过 JavaScript 代码手动删除; - 安全性:
Cookie
的安全性较低,因为Cookie
在每次HTTP
请求中都会自动发送到服务器,存在被窃取或篡改的风险。而LocalStorage
的数据仅在浏览器端存储,不会自动发送到服务器,相对而言更安全一些;
总结
Cookie
适合用于在客户端和服务器之间传递数据、跨域访问和设置过期时间,而 LocalStorage
适合用于在同一域名下的不同页面之间共享数据、存储大量数据和永久存储数据。选择使用哪种机制应根据具体的需
来源:juejin.cn/post/7248623545219825723