# Cookie 中的 SameSite 设置

作者: 刘俊 日期: 2020-06-15

# Cookie 中的 SameSite 设置

HTTP 协议本身是无状态的。什么是无状态呢,即服务器无法判断用户身份。Cookie 实际上是一小段的文本信息(key-value 格式)。客户端向服务器发起请求,如果服务器需要记录该用户状态,就使用 response 向客户端浏览器颁发一个 Cookie。客户端浏览器会把 Cookie 保存起来。当浏览器再请求该网站时,浏览器把请求的网址连同该 Cookie 一同提交给服务器。服务器检查该 Cookie,以此来辨认用户状态。

第一方 cookie 指的是由网络用户访问的域创建的 cookie。例如:当用户通过网络浏览器点击简书 jianshu.com 时,浏览器会在第一个页面中发送一个网页请求,这个过程需要用户直接与 jianshu.com 互动例如登录什么的。这样网络浏览器随后就将此数据文件保存到 jianshu.com 域名下的用户计算机上。 保存到本地的cookie文件

第三方 cookie 是建立在别的域名不是你访问的域名(地址栏中的网址), 比如:广告网络商就是最常见的第三方 cookies 的来源,他们用它们在多个网站上追踪用户的行为,当然这些活动可以用来调整广告。此外图像、 JavaScript 和 iframe 通常也会导致第三方 cookies 的生成。

解释一下广告是如何精准投放的。首先我们所看到的广告都是由一些互联网巨头集合中小网络媒体资源,通过联盟平台帮助广告主实现广告投放,并进行数据监测统计,当你的网站或博客有一定的流量时可以去这些广告联盟官网进行申请。以百度联盟为例:使用百度的时候,会把你的此次搜索保存到 cookie 中,并且分配这个浏览器唯一可标识的 ID 号,当打开人人影视的时候,该页的广告模块就向第三方也就是广告服务商的服务器去请求百度保存在浏览器的 cookie,然后就可以知道你最近浏览或者搜索过哪些商品,然后就返回给你相关的广告。

我们可以在浏览器的开发者工具中查看到当前页面的 Cookie: Application cookie查看2

  • 1、客户端发送 HTTP 请求到服务器
  • 2、当服务器收到 HTTP 请求时,在响应头里面添加一个 Set-Cookie 字段
  • 3、浏览器收到响应后保存下 Cookie
  • 4、之后对该服务器每一次请求中都通过 Cookie 字段将 Cookie 信息发送给服务器。 我通过 post 请求一个登录接口,并在登录接口中在响应头里面添加一个 Set-Cookie 字段 代码1 代码2 我们在请求返回的 Response Headers 可以看到 Set-Cookie 字段:和 Request Headers 看到 cookie 字段(Response Headers 和 Request Headers 的作用和区别待补充) 接口请求头里 接口cookie中 当我们再调用这个服务器上的另外一个接口时我们就可以很轻松的拿到这个 cookie 值 代码3 我们就可以通过获取的 cookie 对登录用户进行再次验证,通过其 cookie 中的信息跳转不同的页面。 代码4 另一个接口接收到的cookie

这里提一下前端是只能读取在前端的 cookie 而后台设置的 cookie 只有在同域的情况下才能读取到。

# Name/Value

键值对,可以设置要保存的 Key/Value,注意这里的 NAME 不能和其他属性项的名字一样

# Expires

过期时间,在设置的某个时间点后该 Cookie 就会失效。Cookie 中的 maxAge 用来表示该属性,单位为秒。maxAge 有 3 种值,分别为正数,负数和 0。 如果 maxAge 属性为正数,则表示该 Cookie 会在 maxAge 秒之后自动失效。浏览器会将 maxAge 为正数的 Cookie 持久化,即写到对应的 Cookie 文件中(每个浏览器存储的位置不一致)。无论客户关闭了浏览器还是电脑,只要还在 maxAge 秒之前,登录网站时该 Cookie 仍然有效。当为 0 时表示立即删除 cookie。为负数时到期时间为创建时间之前。运行窗口关闭后会销毁时间到期的 cookie。 为负数

# Domain

Domain 指定了 Cookie 可以送达的主机名。假如没有指定,那么默认值为当前文档访问地址中的主机部分(但是不包含子域名)。但不能将一个 cookie 的域设置成服务器所在的域之外的域。是无效的。 非服务器所在域

# Path

Path 指定了一个 URL 路径,这个路径必须出现在要请求的资源的路径中才可以发送 Cookie 首部。设置为"/"表示允许所有路径都可以使用 Cookie, Domain 和 Path 标识共同定义了 Cookie 的作用域:即 Cookie 应该发送给哪些 URL。

# Secure

标记为 Secure 的 Cookie 只应通过被 HTTPS 协议加密过的请求发送给服务端。使用 HTTPS 安全协议,可以保护 Cookie 在浏览器和 Web 服务器间的传输过程中不被窃取和篡改。

# HTTPOnly

设置 HTTPOnly 属性可以防止客户端脚本通过 document.cookie 等方式访问 Cookie,有助于避免 XSS 攻击。

# SameSite

SameSite 也是这篇博客的主体,首先我们来看看这个参数的作用。 SameSite 属性可以让 Cookie 在跨站请求时不会被发送,从而可以阻止跨站请求伪造攻击(CSRF)。至于什么是 CSRF 这里就不具体说了。 SameSite 可以有下面三种值:

  • 1、Strict 仅允许一方请求携带 Cookie,即浏览器将只发送相同站点请求的 Cookie,即当前网页 URL 与请求目标 URL 完全一致。
  • 2、Lax 允许部分第三方请求携带 Cookie
  • 3、None 无论是否跨站都会发送 Cookie 造成现在无法获取 cookie 是因为之前默认是 None 的,Chrome80 后默认是 Lax。

# 跨域和跨站

首先要理解的一点就是跨站和跨域是不同的。同站(same-site)/跨站(cross-site)」和第一方(first-party)/第三方(third-party)是等价的。但是与浏览器同源策略(SOP)中的「同源(same-origin)/跨域(cross-origin)」是完全不同的概念。 同源策略的同源是指两个 URL 的协议/主机名/端口一致。例如https://127.0.0.1:8000/它的协议是 https,主机名是 127.0.0.1,端口是 8000。

同源策略作为浏览器的安全基石,其「同源」判断是比较严格的,相对而言,Cookie 中的「同站」判断就比较宽松:只要两个 URL 的 eTLD+1 相同即可,不需要考虑协议和端口。其中,eTLD 表示有效顶级域名,注册于 Mozilla 维护的公共后缀列表(Public Suffix List)中,例如,.com、.co.uk、.github.io 等。eTLD+1 则表示,有效顶级域名+二级域名,例如taobao.com等。这部分内容还需要再补充。

# 改变

来看下从 None 改成 Lax 到底影响了哪些地方的 Cookies 的发送。 影响表 从上图可以看出,对大部分 web 应用而言,Post 表单,iframe,AJAX,Image 这四种情况从以前的跨站会发送三方 Cookie,变成了不发送。故这四种情况跨站给第三方发送 Cookie 需要在设置的时候将 SameSite 设置为 None。

# SameSite by default cookies

允许第三方 把这个设置关了就允许所有的第三方 cookie

# Cookies without SameSite must be secure

https 这个设置就是所谓的许多博客提到的 http 设置 SameSite=None 无效必须设置 Secure 的原因。如果把这个设置设置为 Disabled,那么 http 设置 SameSite=None 是有效的。

# Enable removing SameSite=None cookies

在浏览器设置中管理第三方cookie 这个是关于第三方 cookie 是否可以在谷歌设置中chrome://settings/siteData单独删除第三方 cookie。 开启这个设置 关掉这个设置