了解 Cookie

Cookie 是存储在浏览器中的一块数据,用于持久保存网站执行其功能所需的状态和其他信息。

Cookie 是网站存储在用户设备上的一个小文件,其中存储的信息会在浏览器和网站之间来回传输。

每个 Cookie 都是一个键值对,同时包含多个属性,用于控制该 Cookie 的使用时间和位置。这些属性用于设置过期日期或指示 Cookie 只能通过 HTTPS 发送。您可以在 HTTP 标头中或通过 JavaScript 接口设置 Cookie。

Cookie 是可用于向网站添加持久状态的方法之一。多年来,这些功能不断发展壮大,但却给平台留下了一些有问题的旧版问题。为了解决这个问题,浏览器(包括 Chrome、Firefox 和 Edge)正在改变其行为,以强制执行更可保护隐私的默认设置。

Cookie 的实际应用

假设您有一个博客,您想在其中向用户展示“最新资讯”宣传内容。用户可以关闭此宣传广告,之后一段时间内不会再看到它。您可以将该偏好设置存储在 Cookie 中,将其过期时间设置为一个月(2,600,000 秒),并且仅通过 HTTPS 发送该 Cookie。相应标头如下所示:

Set-Cookie: promo_shown=1; Max-Age=2600000; Secure
在响应中从服务器发送到浏览器的三个 Cookie
服务器使用 Set-Cookie 标头设置 Cookie。

当读者查看符合这些要求的网页时(即连接安全且 Cookie 不超过一个月),其浏览器会在请求中发送此标头:

Cookie: promo_shown=1
浏览器在请求中向服务器发送的三个 Cookie
您的浏览器会在 Cookie 标头中发回 Cookie。

您还可以使用 document.cookie 在 JavaScript 中添加和读取该网站可用的 Cookie。向 document.cookie 赋值将创建或覆盖具有该键的 Cookie。例如,您可以在浏览器的 JavaScript 控制台中尝试以下操作:

→ document.cookie = "promo_shown=1; Max-Age=2600000; Secure"
← "promo_shown=1; Max-Age=2600000; Secure"

读取 document.cookie 将输出当前上下文中可访问的所有 Cookie,每个 Cookie 之间以英文分号分隔:

→ document.cookie;
← "promo_shown=1; color_theme=peachpuff; sidebar_loc=left"
JavaScript 访问浏览器中的 Cookie
JavaScript 可以使用 document.cookie 访问 Cookie。

如果您在一些热门网站上尝试此操作,就会发现其中大多数网站设置的 Cookie 远不止三个。在大多数情况下,这些 Cookie 会随向相应网域发出的每个请求一起发送,这会带来一些影响。对于您的用户来说,上传带宽通常比下载带宽更受限制,因此所有出站请求的开销都会增加首字节时间延迟。谨慎设置 Cookie 的数量和大小。利用 Max-Age 属性有助于确保 Cookie 的保留时间不会超过所需时间。

什么是第一方 Cookie 和第三方 Cookie?

如果您返回之前查看的同一组网站,可能会注意到其中包含各种网域的 Cookie,而不仅仅是您当前访问的网域。与当前网站(即浏览器地址栏中显示的网站)的网域匹配的 Cookie 称为第一方 Cookie。同样,来自当前网站以外的网域的 Cookie 称为第三方 Cookie。这并不是一个绝对标签,而是相对于用户所处环境而言的;同一 Cookie 可以是第一方 Cookie,也可以是第三方 Cookie,具体取决于用户当时所处的网站。

同一网页上不同请求向浏览器发送的三个 Cookie
Cookie 可能来自一个网页上的各种不同网域。

继续沿用之前的示例,假设您的某篇博文中有一张特别可爱的猫的照片,该照片托管在 /blog/img/amazing-cat.png。由于这张图片非常棒,因此其他人直接在自己的网站上使用了它。如果访问者之前访问过您的博客,并且拥有 promo_shown Cookie,那么当他们查看其他人网站上的 amazing-cat.png 时,该 Cookie 将随图片请求一起发送。这对任何人来说都不是特别有用,因为 promo_shown 未用于此人的网站上的任何内容,只是增加了请求的开销。

如果这是无意中造成的,您为什么要这样做?正是这种机制使得网站在第三方情境中使用时能够保持状态。例如,如果您在自己的网站上嵌入 YouTube 视频,那么访问者会在播放器中看到“稍后观看”选项。如果访问者已登录 YouTube,则第三方 Cookie 会在嵌入式播放器中提供该会话,这意味着“稍后观看”按钮只需一步即可保存视频,而无需提示访问者登录或将访问者从您的网页导航到 YouTube,然后再返回。

在三种不同上下文中发送的同一 Cookie
在第三方情境中,当访问不同网页时,系统会发送 Cookie。

网络的文化属性之一是默认情况下往往是开放的。这使得许多人能够在上面创建自己的内容和应用。不过,这也带来了一些安全和隐私问题。跨站请求伪造 (CSRF) 攻击依赖于以下事实:无论谁发起请求,Cookie 都会附加到针对给定来源的任何请求中。例如,如果您访问 evil.example,则该网站可以触发对 your-blog.example 的请求,而您的浏览器会愉快地附加相关 Cookie。如果您的博客在验证这些请求时不够谨慎,evil.example 可能会触发删除帖子或添加其自有内容等操作。

用户也越来越清楚 Cookie 如何用于跟踪其在多个网站上的活动。不过,到目前为止,还没有一种方法可以明确声明您对 Cookie 的意图。您的 promo_shown Cookie 应仅在第一方环境中发送,而旨在嵌入到其他网站上的 widget 的会话 Cookie 则有意在第三方环境中提供已登录状态。

您可以通过设置适当的 SameSite 属性,明确声明您对 Cookie 的意图。

如需识别第一方 Cookie 并设置适当的属性,请参阅第一方 Cookie 方案