避免将 JWT 存储在 localStorage 中
在文章中《》介绍过使用 的好处,如无状态、自我存储等, 也提到过将 存储在 中的方式。可能有人会疑问,使用了 Token 为什么还用 ,可以把 存储在本地,如 。
看到很多文章介绍将 JWT 存储在 中,事实上,个人觉得建议最好不要。这就是将敏感信息存储在 中,对于安全问题来说是个挑战,对于客户端的行为在安全问题上多数是不可靠的。
先简单介绍一下本地存储。
本地存储
是 HTML5 的一项新特征,它基本上允许 Web 开发人员使用 JavaScript 在用户的浏览器中存储想要的任何信息,十分简单。
在操作上, 只是一个可以添加或删除数据的 JavaScript 对象,下面是一段 操作的示例代码,该代码片段将创建一个指定 的 数据,并可以为其更新、删除数据。
export const useStorage = (
valKey = "authorization",
keyPrefix = "DevPoint"
) => {
const localKey = `${valKey}.${keyPrefix}`;
const save = (data) => {
window.localStorage.setItem(localKey, JSON.stringify(deepCopy(data)));
};
const get = () => {
const localData = window.localStorage.getItem(localKey);
if (localData && localData !== "") {
return JSON.parse(localData);
} else {
return false;
}
};
/**
* 清除 localStorage 中 valKey 的值
*/
const clear = () => {
window.localStorage.setItem(localKey, "");
};
return {
save,
get,
clear,
};
};
// 清除所有的 localStorage
export const cleanAll = () => {
window.localStorage.clear();
};
打开浏览器开发工具,在控制台窗口的 的标签页下看到,左侧的 可以看到,如下图所示:

是一个纯 JavaScript 对象。如果正在构建一个单页面站点,使用 之类的东西意味着网页可以独立于任何 Web 服务器运行,只需要浏览器存储空间,而无需在服务器中存储任何数据。
此外, 的好处是大小限制:像 一般是 的大小限制,而 在所有主流浏览器中至少 的数据存储。因此现在也越来越多的 Web 应用使用 来存储一些数据。
安全问题
尽管使用简单,但在安全问题上,没有任何的保护措施,这就意味着敏感信息存储在 会带来安全问题。
将任何敏感信息存储在 中相当于在互联网中发布了这些信息。 设计的目的是为浏览器增加本地存储机制,被设计为简单的 存储,开发人员可以使用它来构建稍微复杂的单页应用程序。
当将敏感信息存储在 中时,实际上是在使用世界上最危险的东西 将最敏感的信息存储在有史以来最糟糕的保险库中,绝对不是一个好注意
如果攻击者可以在您的网站上运行 JavaScript,他们就可以检索您存储在 中的所有数据并将其发送到他们自己的域中。这意味着存储在 中的敏感信息都有可能受到损害。
当然可能有足够的信息认为 Javascipt 无法在您的站点中运行,但是如果您的站点包含来自域外源的第三方 JavaScript 代码,例如一些第三方脚本库的CDN源:
bootstrap 源
jQuery
广告脚本
谷歌分析链接
跟踪脚本
...
一旦出现第三方脚本库被攻击了就会带来安全上的威胁,或许不曾使用第三方脚本库,又或者第三方脚本库绝对安全。
如果需要考虑所有可能的场景,为了降低安全事故的风险,建议尽量不要在 中存储任何重要的敏感信息。
JWT 本质上与 在功能上相同,一旦知道 JWT 就相当于知道了用户名和密码。
如果攻击者可以获得 JWT 副本,就可以神不知鬼不觉的伪造请求向网站发出请求,因此建议不要将敏感信息存储在 中。
存储在 HttpOnly Cookie
本文只是介绍了将 JWT 存储在 的不好,不推荐这样使用。
建议的方式是将JWT存储在 中,优点是不需要在 JavaScript 代码中处理 , 后续请求中都会自动跟上 Token 信息的 。
再者 Cookie 的 HttpOnly 标签是防御 的解决方案之一,因为 在简单的条件下阻止客户端(JavaScript)访问 。如果再将 标志设置为 ,则只会在安全或加密的网络中使用 ,从而增加其安全性。
虽然上面的方式可以防御 ,但还存在另一个威胁即跨站请求伪造(CSRF),可以采用 CORS 白名单机制,并且 CSRF 令牌 与 JWT 一起使用。
但是在某些情况下,例如当 API 被移动应用程序使用并且它需要 标头而不是 时,或者当需要使用同一个 JWT 向多个后端发出 HTTP 请求时,把 JWT 存在 中的方案就更方便。
还有一点 Cookie 存储的大小为 4KB ,因此在使用这个方案的时候需要注意 JWT 的大小。如果 JWT 超过了 就不适合使用 Cookie 存储 JWT的方案。
总结
JWT 是一个非常流行的标准,可以使用签名来信任请求,并在各方之间安全的交换信息。在实际项目开发中,建议避免将 JWT 存储在 中,而是存储在 。