谷歌准备停用第三方 Cookie,淘汰前再学一把!

964 阅读8分钟

就在前两天,谷歌浏览器开始推出 停用第三方 cookie 的计划

虽说目前只针对少数用户推广了这个计划,但是说不定在未来某一天,谷歌就会全面停用 coookie

为了应对这个变化,今天就和大家一起回顾一下 cookie 的相关知识;知己知彼方能百战不殆 💪💪💪!

cookie 诞生的原因

各位小伙伴在浏览网页的时候,或多或少都有遇到这样的情况 —— 当你登录某个网站后,下次再次打开这个网站的时候,你会发现你还是登录状态不需要再次登录。

这种 记录登录状态的机制 实际上就是通过 cookie 来实现的;我们来简单了解一下它的原理:

登录状态保存原理

当用户点击登录按钮,前端会将用户名密码发送给服务器;服务器验证用户名和密码,如果验证通过就在服务器端创建一个 session 对象;

然后服务端会将 session 对象的唯一标识符 (session id) 通过响应头Set-Cookie: <cookie-name>=<cookie-value> 这种形式发送给浏览器。

服务端设置 cookie:

res.setHeader('Set-Cookie', 'sessionid=xxxx');

接着,浏览器检测到响应头中有 Set-Cookie 字段,就会 自动将这个字段中的值存储到浏览器 Application 中的 cookies

下次再次请求相同的服务器的时候,浏览器会将 cookie 的值 (session id) 放到 请求头中的 Cookie 字段 发送给服务器。

请求头携带 cookie:

image.png

服务器接收到请求头 Cookie 中的 session id 之后,会根据 session id 查找对应的 session 对象,如果 找到了说明用户之前已经登录过了,就不需要再次登录了

cookie 的特点

在登录状态保存的例子中,cookie 的作用主要是用于记录 session id;所以也可以用其他的方式代替 cookie 来储存,比如:localStoragesessionStorageIndexedDB 等等。

那和这些方式相比,cookie 有什么特点使得它更受青睐呢?

下面我们就来介绍一下 cookie 的一些特性:

自动携带

在前面的例子中,我们知道浏览器会 自动cookie 中的值通过 请求头中的 Cookie 字段 发送给服务器。

这样做的好处是,我们就不需要手动的设置请求头了;但是同时因为每次请求都会自动携带 cookie 的值,也会 导致额外的流量消耗

注意:自动携带 cookie 受到 SameSite 属性的限制,在后面安全限制模块中会详细介绍。

过期删除

Expires/Max-Age

服务端可以通过 Set-Cookie 字段来设置 cookie 的过期时间,浏览器会自动删除过期的 cookie

如果没有设置过期时间,cookie 只在本次会话中有效,浏览器关闭的时候自动删除

举个例子:

// 设置 cookie 的过期时间为 2024-01-10 05:52:22
res.setHeader('Set-Cookie', 'name=jack;Expires=Wed, 10 Jan 2024 05:52:22 GMT');
// 设置 cookie 的过期时间为 1000 秒后
res.setHeader('Set-Cookie', 'name=jack;Max-Age=1000');

注意:这里的过期时间都是相对 客户端的时间

安全限制

我们知道,cookie 是存储在浏览器中的,如果 cookie 的值被恶意获取到,那么就会造成安全问题。

因此 cookie 提供了一些属性来 设置安全限制,防止 cookie 的值被恶意获取到

httpOnly

如果你的网页被恶意注入了一些恶意脚本,那么这些恶意脚本就可以通过 document.cookie 来获取到 cookie 的值。

为了防止这种情况的发生,cookie 提供了 httpOnly 属性,如果设置了 httpOnly 属性,那么通过 document.cookie 就无法获取到 cookie 的值

Secure

如果设置了 Secure 属性,那么 cookie 只能在 https 协议 下才能使用。

htps 协议是经过加密的安全协议,所以可以保证 cookie 的安全性。

SameSite

SameSite 属性用于设置 跨站请求 时是否携带 cookie

还记得我们之前说过,浏览器会自动携带 cookie 吗?实际上是否自动携带 cookie 是受 SameSite 属性限制的。

它有三个值:

  • Strict禁止在跨站请求中携带 cookie,只能在同站请求中携带 cookie;
  • Lax:如果没有显示的设置 samesite 属性,那么 默认就是 Lax
    表示只能 在部分跨站请求中携带 cookie,比如:get 请求、a 标签跳转等等;而在 post 请求、iframeimage 等中禁止携带 cookie
  • None:在 同站和跨站请求中都可以携带 cookie;但是需要同时设置 secure 属性

这里要注意区分一下跨站与跨域的概念:

跨域

一个网站地址由:协议 + 域名 + 端口 三部分组成,如果两个网站的协议、域名、端口中 有一个不同,那么就是跨域。

跨站

而两个网站的协议以及 有效顶级域名(eTLD)+ 它上一个域名相同,那么就是同站

所有的有效顶级域名(eTLD)可以在这个地址找到:公共后缀列表

举个例子:对于 www.google.co.uk 这个地址 ——

  • 协议:https
  • 有效顶级域名(eTLD):co.uk
  • 有效顶级域名(eTLD)+ 上一个域名:google.co.uk

因此这个例子中的网站为:www.google.co.uk

URL是否同站原因
www.google.co.uk完全相同,同站
www.google.co.uk:8080端口不同,仍然是同站
www.login.google.co.uk子域名不同,仍然是同站
www.github.co.uk有效顶级域名(eTLD)不同,跨站

更简单的判断方法是通过浏览器请求头中的 Sec-Fetch-Site 字段来判断是同站还是跨站。 这个字段有三个值:

  • same-origin:同域;
  • same-site:同站;
  • cross-site:跨站;
  • none:这个请求与站点无关,比如:请求输入 url、打开书签等等。

注意:SameSite 属性设置为 None 时必须和 Secure 属性一起使用,否则会报错。

指定作用域

除了提供安全保障外,cookie 还可以通过 Path 属性和 Domain 属性来 指定作用域,从而限制 cookie 的使用范围。

Domain

Domain 用于 指定 cookie 可以被哪些域名访问

可以通过请求头的 Set-Cookie 来设置 Domain 属性:

// 设置 cookie 的有效域名为 baidu.com
res.setHeader('Set-Cookie', 'name=jack;domain=baidu.com');

如果 没有设置 Domain 属性,那么 cookie 的有效域名就是 当前域名

如果 设置了 Domain 属性,那么 cookie 的有效域名 包含设置的域名以及设置域名的子域名

举个例子:假设当前域名为 www.baidu.com

DomainURL是否能够访问 cookie
www.baidu.comwww.baidu.com
www.baidu.comwww.tieba.baidu.com
www.baidu.comwww.google.com
未设置www.baidu.com
未设置www.tieba.baidu.com
未设置www.google.com

注意: domain 属性必须是当前域名的父域名或者是当前域名本身,否则会报错。
例如,当前域名为 www.baidu.com,那么 domain 属性可以设置为 www.baidu.com、www.tieba.baidu.com 等等;但是不能设置为 www.google.com。

Path

Path 属性用于指定 **哪些 URL 可以访问 cookie **,只有满足条件时浏览器才会携带 cookie

同样可以通过请求头的 Set-Cookie 来设置 Path 属性,如果没有设置 Path 属性,那么默认的 Path 属性为 '/'

举个例子: 设置 cookie 的有效路径为 '/user'

// 设置 cookie 的有效路径为 /user
res.setHeader('Set-Cookie', 'name=jack;path=/user');
PathURL是否携带 cookie
'/user'www.baidu.com
'/user'www.baidu.com/login
'/user'www.baidu.com/user
'/user'www.baidu.com/user/login
'/user'www.baidu.com/user/center

其它属性

在前面我们详细介绍了 cookie 的一些特点,最后再来简单介绍一下剩余的属性:

Size

Size 属性是由浏览器自动计算的,表示 cookie大小,不能手动设置与修改。

Priority

这个属性只有在谷歌浏览器中才支持,它用于设置 cookie 的 优先级;它包含三个值:

  • Low:优先级低;
  • Medium(默认值):优先级中;
  • High:优先级高;

每个域下能够保存的 cookie 数量是 有限的;如果设置了 priority 属性,那么浏览器会 优先删除优先级低的 cookie

Partition Key

这个属性用于 隔离不同网站的 cookie,从而提高用户的隐私和安全性。

在没有 Partition Key 的情况下,假设你访问了一个网站 A,这个网站 A 嵌入了一个第三方服务 C;并且这个第三方服务 C 在你的浏览器中设置了一个 cookie

随后,你又访问了另一个网站 B,这个网站同样使用了相同的第三方服务 C。

由于没有使用 cookie 分区,这个 第三方服务 C 可以读取它之前在网站 A 上设置的 cookie;这意味着,第三方服务 C 可以跟踪你在不同网站上的活动。

而使用了 Partition Key 进行分区后,当用户访问新网站(例如网站 B)时,嵌入的 C 框架将不会收到在网站 A 中嵌入 C 时设置的 cookie

打开开发者工具,然后依次打开 Application > Storage > Cookies

在这里就能看到 cookie 的所有属性了。

总结

以上就是本次关于 cookie 的全部介绍啦。虽然说出于隐私安全等因素考虑,cookie 或许在不久的将来就会被全面淘汰。

但是作为一个合格的前端 cv 工程师,还是有必要了解它的特性,这样在遇到问题时才能游刃有余,秀翻同事和面试官!