HTTP 超文本传输协议是一种无状态协议。根据 Wikipedia,它之所以无状态,是因为它“不需要 HTTP 服务器在不同请求期间保留用户的信息或状态”。
今天,网站服务依然是如此实现的 – 输入浏览器的URL,浏览器向某处的服务器发出请求,然后服务器返回文件以呈现页面,然后关闭连接。
现在,假设需要登录网站以查看某些内容,例如使用 LinkedIn。该过程与上述过程基本相同,会看到一个表单,用于输入电子邮件地址和密码。
输入相关信息,然后浏览器将其发送到服务器。服务器检查登录信息,如果一切顺利,它将把呈现页面所需的数据发送回浏览器。
但是,如果 LinkedIn 是无状态的,一旦跳转到另一个页面,服务器将不记得你刚刚已经登录过。它将要求你再次输入电子邮件地址和密码,进行检查后在发送数据以渲染新页面。
那会非常令人沮丧,不是吗?许多开发人员也这样认为,并找到了很多在 Web 上创建有状态会话的方法。
90 年代初期,Netscape 的开发人员 Lou Montoulli 遇到了一个问题 – 他正在为另一家公司 MCI 开发一个在线商店,该商店会在服务器中存储每个客户购物车中的商品。这意味着人们必须首先创建一个帐户,创建账户需要花费一些时间,存储每个用户购物车的内容也会占用大量存储空间。
MCI 要求将这些数据存储在客户自己的计算机上。他们还希望客户在没有登录时也能添加商品到购物车。
为了解决这个问题,Lou 提出了一个在程序员中已经广为人知的想法:魔力 cookie。
魔力 cookie 或 cookie,是可以在两个计算机程序之间传递的少量数据。它们之所以“魔幻”,是因为 cookie 中的数据通常是随机密钥或令牌,并且实际只对使用它的软件才有意义。
Lou 采用了魔力 cookie 概念,并将其应用于在线商店,后来又应用于浏览器。
现在了解了 cookie 的历史,来看一下如何使用 cookie 在网络上创建有状态会话。
和 cookie 有点像的一个场景,就是你在游乐园中获得的腕带。
当登录网站时,过程就像进入游乐园一样。首先,要买票,然后进入公园时,工作人员会检票并给你一条腕带。
这和登录的方式一样 - 服务器检查你的用户名和密码,创建并存储会话,生成唯一的会话 ID,然后发送回带有该会话 ID 的 cookie。
(请注意,会话 ID 不是你的密码,它是完全独立的,即时生成的。密码处理和身份验证不在本文的讨论范围之内,可以在这里了解更多。)
在游乐园中,可以通过出示腕带来消费项目。
同样,当你向登录的网站发出请求时,浏览器会将带有会话 ID 的 cookie 发送回服务器。服务器使用你的会话 ID 检查会话,然后返回请求的数据。
最后,一旦离开游乐园,你的腕带将不再起作用 - 你无法使用它重新回到公园参与游乐活动。
登出网站也一样。浏览器将带有 cookie 的注销请求发送到服务端,服务端删除 session,并告知浏览器删除具有相应 session id 的 cookie。
如果想回到游乐园,则必须购买另一张门票并获得另一个腕带。同样,如果想继续使用网站,就必须重新登录。
图片来源:Session vs Token Authentication in 100 Seconds (YouTube)
这是如何使用 cookie 来记录登录网站状态的简单示例。它还可以用来记录设置的深色主题模式,以及跟踪你在网站上的其它行为等。
现在已经了解了 cookie 的历史以及它们的作用,接下来来看一下 cookie 的一些局限,然后用实例演示一下。
与浏览器中更常用的存储数据方案(例如,localStorage
或 sessionStorage
)相比,cookie 有很多局限性。这是 cookie 和其它技术对比的摘要:
cookies | Local Storage | Session Storage | |
---|---|---|---|
容量 | 4KB | 10MB | 5MB |
可访问 | 任何窗口 | 任何窗口 | 相同标签页 |
过期 | 手动设置 | 永不过期 | 标签页关闭时 |
存储位置 | 浏览器和服务端 | 仅浏览器 | 仅浏览器 |
通过请求发送 | 是 | 否 | 否 |
cookies 是一种古老的技术,并且容量非常有限。不过,可以使用它们做很多事情。它们的体积小巧,浏览器可以轻松地在每个请求中附带 cookie 发送到服务器。
还值得一提的是,出于安全原因,浏览器仅允许 cookie 在一个域名中可见。
因此,如果你通过 ally.com 登录银行,则 cookie 将仅在该域名及其子域名内起作用。例如,你的 ally.com
的 cookie 可以在 ally.com
,ally.com/about
和域名 www.ally.com
上可见,而在 axos.com
上不可见。
这意味着,即使你同时拥有两个帐户并在 ally.com
和 axos.com
上都进行了登录,这些站点也将无法读取彼此的 cookie。
重要的是要记住,你的 cookie 是随浏览器中的请求一起发送的。这非常方便,但是存在一些严重的安全隐患,后面会详述。
最后,如果本文你只能记住一个知识点,那就请记住,cookie 是公开读取和发送的,切勿在其中存储诸如密码之类的敏感信息。
cookies 实际上只是带有键/值对的字符串。尽管可能更多在后端使用 cookie,但也需要客户端设置 cookie。
以下是在 vanilla JavaScript 中设置 ocokie 的方法:
document.cookie = 'dark_mode=true'
然后,当打开开发者控制台时,单击“Application(应用程序)”,然后在站点的“Cookies”下,将看到刚添加的 cookie:
如果仔细查看 cookie,会发现它的过期日期设置为 Session
。这意味着,当关闭标签页/浏览器时,cookie 将被销毁。
这可能是某些场景的预期行为,例如 cookie 存有付款信息的在线商店。
但是,如果希望 cookie 的存在时间更久,需要设置一个有效期。
要设置过期时间,只需设置 cookie 的值,然后添加带有日期配置的 expires 属性,该日期一般设置为未来的某个时间:
document.cookie = 'dark_mode=true; expires=Fri, 26 Feb 2021 00:00:00 GMT' // expires 1 week from now
JavaScript Date
对象可以很方便的生成日期。可以在此处阅读有关 Date
对象的更多信息。
或者,也可以将 max-age
属性与你希望 cookie 生效的秒数结合使用:
document.cookie = 'dark_mode=true; max-age=604800'; // expires 1 week from now
然后,当到达该日期时,浏览器将自动删除 cookie。
cookie 更新很方便,和是否具有有效期无关。
只需更改 cookie 的值,浏览器就会自动配置:
document.cookie = "dark_mode=false; max-age=604800"; // expires 1 week from now
有时,只希望 cookie 在网站的某些部分生效。如何操作取决于网站的设置方式,一种方法是使用 path
属性。
配置 cookie 的方法如下:使 cookie 仅在 /about
的 about 页面上起作用:
document.cookie = 'dark_mode=true; path=/about';
现在,cookie 仅能在 /about
和其他子目录(例如 /about/team
)上生效,而不能在/blog
上生效。
然后,当访问 about 页面并查看 cookie 时,如下:
要在 JavaScript 中删除 cookie,只需将 expires
属性设置为已过的日期即可:
document.cookie = 'dark_mode=true; expires=Sun, 14 Feb 2021 00:00:00 GMT'; // 1 week earlier
也可以使用 max-age
并将其设置为负值:
document.cookie = 'dark_mode=true; max-age=-60'; // 1 minute earlier
然后,查看 cookie,会发现它已经被删除:
这应该是在 vanilla JS 中使用 cookie 所需了解的比较全面的知识。
我们介绍的所有内容都能够满足常见的需求,如果对 cookie 的使用比较频繁,可以考虑类库 JavaScript Cookie 或 Cookie Parser。
通常,cookie 在正确配置的前提下非常安全。浏览器有很多内置的限制,我们之前已经介绍了这些限制,部分原因是该技术的年代久远,这反而提高了其安全性。
尽管如此,攻击者还是有一些办法窃取你的 cookie 并利用它来搞破坏。
我们将探讨一些常见的攻击手段,并介绍对该攻击的应对策略。
另外,请注意,所有代码段都将使用 。如果要在服务器上实现这些修补程序,则需要查找语言或框架的确切语法。
中间人(MitM)攻击描述了广泛的攻击类别,其中,攻击者在客户端和服务器之间,并拦截在两者之间传递的数据。
图片来源:Man-in-the-Middle Attacks and How To Avoid Them
这可以通过多种方式完成:通过访问或收听不安全的网站,模仿公共 WiFi 路由器,DNS 欺骗或通过 SuperFish 一类的恶意软件/广告软件。
这是 MitM 攻击的比较深入的介绍概述,涉及了网站如何保护自己和用户。
提示:视频的开头谈论了斯科茨女王玛丽,并生动地描绘了她的斩首。它有一点点暴力,但是如果你想跳过它,请跳至 00:57 处播放。
或是邮件反馈可也:
askdama[AT]googlegroups.com
订阅 substack 体验古早写作:
关注公众号, 持续获得相关各种嗯哼: