Cookies、本地存储和会话存储
我们很多人都听说过会话存储、本地存储和 Cookie。但它们到底是什么?它们解决了什么问题?它们之间又有什么区别?
曲奇饼
最初,Web 使用 HTTP 协议发送消息(顺便说一句,SSL 更安全,你应该使用 HTTPS 而不是 HTTP)。这些协议是无状态协议。在无状态协议中,每个请求不存储任何状态或“持久信息”;每个请求都是一个独立的“孤岛”,它不知道其他请求的存在。
无状态协议可以优化性能,但也存在一个问题:如果需要记住用户会话怎么办?如果使用无状态协议darkMode: true
,user_uuid: 12345abc
服务器该如何记住?答案是:用 Cookies!
Cookie 可以通过 HTTP 头设置。通常,如果你尝试访问的服务器有 Cookie,它会发送如下 HTTP 头:
Set-Cookie: choco_chip_cookie=its_delicious
当您的浏览器收到此标头时,它会保存choco_chip_cookie
Cookie。
Cookie 与网站关联。如果您websitea.com
启用了,则您在 时cookie_a
无法查看。您需要在。cookie_a
websiteb.com
websitea.com
要查看你拥有的 Cookie,如果你使用的是 Firefox,请在开发者工具中前往“存储”->“Cookie”;如果你使用的是 Chrome,请在开发者工具中前往“应用程序”->“存储”->“Cookie”。大多数网站都使用 Cookie,你应该能在那里找到一些(如果没有,请前往其他网站)。
Cookie 可以设置有效期。当然,你可以将其设置为一个遥远的未来日期,使其永久有效:
Set-Cookie: choco_chip_cookie=its_delicious; Expires=Mon, 28 Feb 2100 23:59:59GMT;
您可能需要了解的另一个 Cookie 行为是:您的浏览器在每次请求时都会发送 Cookie 。当您访问时https://example.com
,需要发出 30 个请求来下载 HTML 页面及其 29 个资源文件,您的浏览器将发送您的 Cookie(针对https://example.com
域名)30 次,每次请求一个。
这仅适用于您将资源存储在相同域名下的情况,例如example.com/assets/images/cute-cats.svg
、example.com/assets/stylesheets/widgets.css
等。如果您将资源存储在不同的域名/子域名下,例如exampleassets.com/assets/stylesheets/widgets.css
或static.example.com/assets/stylesheets/widgets.css
,则浏览器将不会向该域名发送 Cookie。仅供参考,将资源存储在不同的域名是提高速度的好策略!
Cookies 的最大大小为 4KB。这是合理的,因为 Cookies 会一直被发送。您肯定不希望在访问一个页面时向所有 30 个不同的请求发送 3MB 的 Cookie 数据。即使有这个大小上限,您也应该尽可能减少 Cookies 数量以减少流量。
Cookie 的一个常见用法是,为您的网站使用一个 UUID,并运行一个单独的服务器来存储所有 UUID,以保存会话信息。单独的 Redis 服务器是一个不错的选择,因为它速度很快。因此,当用户尝试访问 时example.com/user_settings
,该用户会发送其 Cookie example.com
,例如example_site_uuid=user_iggy_uuid
,然后您的服务器会读取该 Cookie,然后您的服务器可以将其与 Redis 中的键匹配,以获取用户会话信息供服务器使用。在您的 Redis 服务器中,您将获得类似 的内容user_iggy_uuid: {darkMode: false, lastVisit: 01 January 2010, autoPayment: false, ...}
。
我强烈建议你亲自体验一下。使用 Chrome/Firefox 或任何现代浏览器访问任意网页(确保它启用了 Cookies)。
- 查看您当前拥有的 cookie。
- 现在查看“网络”选项卡并检查请求标头。您应该看到相同的 Cookie 被发送。
您可以使用 Javascript 创建 cookie document.cookie
。
document.cookie = "choco_chip_cookie=its_delicious";
document.cookie = "choco_donut=its_awesome";
console.log(document.cookie);
除此之外Expires
,Cookie 还有很多其他属性,您可以赋予它们来执行各种操作。如果您想了解更多信息,请查看Mozilla Cookie 页面。
Cookie 可以被第三方访问(例如,如果网站使用 HTTP 而不是 HTTPS),因此您需要使用该Secure
属性来确保仅在请求使用 HTTPS 协议时发送 Cookie。此外,使用该HttpOnly
属性可以使您的 Cookie 无法访问,document.cookie
从而防止 XSS 攻击。
Set-Cookie: awesome_uuid=abc12345; Expires=Thu, 21 Oct 2100 11:59:59 GMT; Secure; HttpOnly
一般来说,如果您有疑问,请使用Secure
和HttpOnly
Cookie 属性。
本地存储和会话存储
本地存储和会话存储的相似之处多于不同之处。大多数现代浏览器都支持本地存储和会话存储功能。它们用于在浏览器中存储数据。它们只能从客户端访问(Web 服务器无法直接访问它们)。此外,由于它们是前端工具,因此不支持 SSL。
与 Cookie 不同,所有 Cookie(针对该域名)都会在每次请求时发送,而本地存储和会话存储数据则不会在每次 HTTP 请求时发送。它们只是停留在您的浏览器中,直到有人请求为止。
每个浏览器对于本地存储和会话存储的数据量都有不同的规范。许多主流文献声称本地存储的限制约为 5mb,会话存储的限制约为 5-10mb(为了安全起见,请检查每个浏览器)。
本地存储和会话存储之间的主要区别在于,本地存储没有到期日期,而会话存储数据在您关闭浏览器选项卡时就会消失 - 因此称为“会话”。
这两个存储都可以通过 JavaScript DOM 访问。要设置、获取和删除本地存储数据,请执行以下操作:
localStorage.setItem('strawberry', 'pancake');
localStorage.getItems('strawberry'); // pancake`
localStorage.chocolate = 'waffle';
localStorage.chocolate; // waffle
localStorage['blueberry'] = 'donut';
localStorage['blueberry']; // donut;
delete localStorage.strawberry;
您还可以将类似 JSON 的对象存储在本地存储中。请记住,您需要向其传递一个 JSON 字符串(使用JSON.stringify
)。另外,由于您传递的是 JSON 字符串,因此请不要忘记运行JSON.parse
以获取其值。
localStorage.desserts = JSON.stringify({choco: "waffle", fruit: "pancake", sweet: "donut"});
const favDessert = JSON.parse(localStorage.desserts)['choco']; // waffle
如果您使用的是 Chrome,则可以在 devtool 的“应用程序”选项卡 ->“存储”->“本地存储”中看到刚刚输入的 localStorage 值。如果您使用的是 Firefox,则可以在 devtool 的“存储”选项卡中的“本地存储”下找到它。
使用 Javascript 访问会话存储与访问本地存储类似:
sessionStorage.setItem('strawberry', 'pancake');
sessionStorage.getItems('strawberry'); // pancake`
sessionStorage.chocolate = 'waffle';
sessionStorage.chocolate; // waffle
sessionStorage['blueberry'] = 'donut';
sessionStorage['blueberry']; // donut;
delete sessionStorage.strawberry;
两种存储都与域名相关,就像 Cookies 一样。如果您localStorage.setItem('choco', 'donut');
在 中运行,并且在 中https://example.com
运行,则本地存储项仅存储在 中,而存储在 中。localStorage.setItem('choco', 'bo');
https://whatever.com
choco donut
example.com
choco bo
whatever.com
本地存储和会话存储均由浏览器厂商定义。如果您使用 Chrome 浏览器存储,则无法从 Firefox 读取。
Cookies、本地存储和会话存储
总结一下:
曲奇饼
- 有不同的到期日期(服务器或客户端都可以设置到期日期)
HttpOnly
如果该标志为真,则客户端无法访问 Cookies- 具有 SSL 支持
- 每次 HTTP 请求时都会传输数据
- 4kb 限制
本地存储
- 没有有效期
- 仅限客户端
- 不支持 SSL
- 每次 HTTP 请求时都不会传输数据
- 5mb 限制(请通过浏览器检查)
会话存储
- 关闭浏览器标签页时数据就会消失
- 仅限客户端
- 不支持 SSL
- 每次 HTTP 请求时都不会传输数据
- 5-10 mb 限制(请通过浏览器检查)