Cookie教程-samesite属性


如果你对`samesite`已经有所了解,只是想迅速查看一下几个可选值的含义,可以直接往后翻。

samesite属性的含义

samesite表示是否允许跨站请求时携带Cookie。 也可以换一句话解释,samesite表示是否允许当前Cookie作为第三方Cookie被发送到服务端。 举一个实际一点的例子来解释: 银行网站在浏览器端种了一个用于身份认证的Cookie,钓鱼网站在浏览器端给银行网站的服务端发请求时,能否带上这个Cookie,这由该Cookie的samesite属性决定。

samesite属性和值都不区分大小写。 samesite属性可以有如下值:strictlaxnone

名词解释

第三方Cookie

所谓第三方Cookie,通用定义是这样的: 浏览器当前访问的网站是第一方。 用户是第二方。 网站在浏览器中向其他Http服务发出请求,这个Http服务就是第三方。

如何判断是否是"其他服务""其他站点",请看下面的"相同站点的判断规则"。

相同站点的判断规则

如何判定两个网站是否是同一个网站? 例如:a.itthink.techb.itthink.tech是同一个网站吗?

规则是这样的,一般情况下,当两个网站URL中域名的公共后缀相同,且公共后缀前面的那一级域名也相同时,那就认为是同一个网站。

什么是公共后缀comorgnettech都是公共后缀。但是远不止这些,已知的公共后缀在这里:publicsuffix.org/list/public... 这里要注意的是,github.io也是公共的后缀,因为a.github.iob.github.io分别代表完全不同的项目主页。a项目和b项目毫不相干,但是它们都共享github.io域名,因此github.io这种知名站点就成了公共后缀,因此a.github.iob.github.iosamesite规则认为是不同的网站。

很显然具有相同公共后缀域名的两个网站不一定是同一个站点,那就继续看公共后缀的下一级。 a.itthink.techb.itthink.tech的公共后缀都是techtech的下一级都是itthink,那samesite的规则就认为a.itthink.techb.itthink.tech是同一个网站。

以上便是一些名词和概念解释。 在讲samesite的各个值之前,我们还需要了解一下CSRF(跨站请求伪造)攻击,这样可以更深刻的理解samesite

CSRF(跨站请求伪造)攻击

举例如下: 某银行网站bank.com在用户登录后会种一个用于身份认证的Cookie。

某钓鱼网站bunk.com在研究了银行网站转账的Http接口/transfer后,在钓鱼网站上放了一个表单提交按钮,点击按钮会向该接口提交数据,接口的参数被设置为当前用户账户给钓鱼网站账户转账。

用户登录银行网站bank.com,并没有登出,而是继续访问了钓鱼网站bunk.com并点击了其表单提交按钮,此时Cookie会一并被发送到银行服务器,由于有Cookie存在,银行验证通过,钓鱼网站成功将用户的钱转入自己的账户,攻击顺利完成。 以上便是著名的CSRF(跨站请求伪造)攻击。 画图示例如下:

正如我们做了一把枪,本想留给自己人使用的,没曾想被坏人拿过去打我们自己人。我们不能阻止别人拿枪,但是我们可以给子弹加点智能,当它发现当前使用枪的人不是自己人时,子弹就发不出去。这个子弹就是Cookie。

有了以上这些知识后,咱们就可以理解samesite具体的值了。

可选值"strict"

为了避免CSRF攻击,最有效的方法就是禁止在跨站请求中携带Cookie。 samesite=strict可以全面的防止跨站请求携带Cookie。 具体包括下面两种情况:

  1. Cookie只有在所属的网站发请求时才能被带上,从其他网站的页面向Cookie所属网站的服务器发任何请求时,请求中不会有Cookie。
  2. 从其他网站跳转到Cookie所属的网站时,也不会带上所属网站的Cookie。

这里所说的"请求"均是指从浏览器端向服务器发送的请求。 是否是"其他网站"请参考上面说的"相同站点的判断规则"。

对于情况1我们大部分情况下是可以接受的。 但是对于情况2,可能会影响用户体验。因为根据情况2的规则,从其他网站跳转到我们的网站时,我们预存在浏览器中的Cookie是不会被发送的。如果我们的网站根据Cookie来做出反应的话,那将会导致网站返回的内容和用户的期望不一致。例如用户已经登录过了,但是从其他网站跳转过来时,由于服务端接收不到Cookie,还会要求用户重新登录。

之所以会有情况2这种苛刻的限制也是有原因的。因为攻击者可以在跳转的URL中伪造参数,从而在用户点击链接跳转时对其进行攻击。

但是这确实会一定程度上影响用户体验。

这时我们还有其他选择,请往下看。

可选值"lax"

lax值也是不允许跨站请求时携带Cookie。但是它有两个例外。

  1. 浏览器地址跳转到Cookie所属网站且是GET请求时,会带上Cookie。
  2. <link rel="prerender">标签对即将要跳转的网页发送请求进行预渲染时,会带上Cookie。 放宽了这两个限制,我们的用户体验会比"strict"好一些。但是我们一定要确保GET类的请求都是安全的,幂等的,否则将是一个大漏洞。

我们前后端分离的站点,前端域名有可能会和数据接口的域名属于不同站点(不同站点的规则请看上面的名词解释),假设后端接口有种Cookie的需求,那这种情况下,用strictlax值都会有很大的问题,因为这属于跨站请求中携带Cookie的情况,Cookie会被禁止发送。

samesite属性还提供了第三个值none来应对这种情况,这是samesite最宽松的设置,就和不支持samesite属性的浏览器行为一样。

可选值"none"

对跨站请求是否可以携带Cookie没有限制。 鉴于该属性过于宽松,IETF后来在一个渐进式改善Cookie的提案中提出当使用samesite=none时,Cookie必须有secure属性,否则整个Cookie的设置无效。这里就不列出各个浏览器具体哪个版本开始这么做了,大家就记住加上secure就可以了。 secure属性规定Cookie只能在Https请求中被发送,甚至只能在Https请求中被种下。

对于前后端分离的场景,如果前后端域名不属于同一站点,那就只能设置成none了。不过这种情况下,如果希望Ajax或者fetch请求携带Cookie,还需要加上以下配置:

  1. 浏览器端:给XMLHttpRequest的对象加上withCredentials=true属性,Fetch也需要相应的withCredentials相关配置,其配置更为细腻,这里就不多说了。
  2. 服务端:后端数据服务需加上Access-Control-Allow-Credentials响应头。 否则Cookie仍然无法发送。

none值还有一个巨大的问题,就是某些浏览器的版本对该属性的支持不好,有可能会导致整个Cookie的设置无效。这确实是一个非常头疼的问题。现阶段我们可以像这样去设置Cookie,以便避免这样的问题: Http端:

ini 复制代码
Set-cookie: 3pcookie=value; SameSite=None; Secure
Set-cookie: 3pcookie-legacy=value; Secure

Javascript端:

ini 复制代码
// 新样式的Cookie
document.cookie = '3pcookie=value; SameSite=None; Secure';
// 旧样式的Cookie
document.cookie = '3pcookie-legacy=value; Secure';

以上建议来自于谷歌的开发者网站web.dev/samesite-co... 注意SameSite=None; Secure大小写均可,如果你们团队有代码规范,那就按照规范写。 在获取Cookie时,可以先检查新样式的Cookie是否存在,如果不存在再检查旧样式的。

不得不说这对于我们开发者来说又是一个新噩耗。建议公司团队对Cookie的操作进行封装,然后统一升级。

samesite的三个可选值均已讲完。 如果我们不设置samesite,它的默认值是什么呢?请往下看。

samesite的默认值

起初samesite的默认值是none,毕竟只有这样才能做到最好的向后兼容。 但是这一情况正在从19年开始慢慢改变,新的默认值将是samesite=lax

过渡方案:两分钟内非安刷新跳转请求可带Cookie

所谓刷新跳转请求,也可以叫顶层导航请求,就是说浏览器地址栏会变,浏览器会刷新的Http请求。

在变成lax之前,有临时过渡方案来给开发人员一定的时间逐步完善Cookie设置。 在过渡方案中,samesite没有显式设置时,浏览器的大部分行为会和lax相同,但是允许Cookie被种下的两分钟内,浏览器刷新跳转时,使用非安全的Http method发请求时也能带上Cookie(前提是Cookie的domain和请求的URL域名匹配)。 举例如下: 当用户访问a.com网站时,请求itthink.tech服务种下Cookie:t=xyz; domain=itthink.tech; path=/,然后用户在两分钟内点击表单提交按钮,表单的method="POST"action="https://www.itthink.tech/login",在samesite的默认值临时方案中,虽然a.comitthink.tech是完全不同的站点,且是非安全的POST请求,但是这个表单请求依然可以带上Cookie:t=xyz。 这种跨站提交其实有一定的CSRF(跨站请求伪造)风险,但是为了让开发人员有时间逐步完善Cookie设置,这种临时方案有一定的必要性。

虽然现在有临时方案,但是最终肯定是会将默认值彻底变成lax。因此大家从现在开始就可以给samesite加上明确的值了,如果拖下去,后续会面临各个不同厂家和版本的浏览器的不同表现,到时候就比较挠头了。

另外Safari和Firefox这些浏览器都在逐步杜绝第三方Cookie,在禁用第三方Cookie的情况下,samesite其实用处已经不是很大了。但是Chrome到目前为止其第三方Cookie还是放开的状态,而Chrome是当今全球市场份额占比最高的浏览器,因此samesite对于Cookie安全还是挺重要的。

samesite的意义

优点:samesite确实对防范CSRF(跨站请求伪造)有很好的作用,虽然目前还没有成为正式标准,但是标准已经在路上了,也被各大浏览器厂商广为接受,广泛实现。

缺点:samesite并不能防止隐私泄漏,也不能防止Cookie被盗取。Cookie相关的安全和隐私泄漏问题还有很多。

此篇结束。

相关推荐
中微子6 分钟前
JavaScript 防抖与节流:从原理到实践的完整指南
前端·javascript
天天向上102421 分钟前
Vue 配置打包后可编辑的变量
前端·javascript·vue.js
芬兰y37 分钟前
VUE 带有搜索功能的穿梭框(简单demo)
前端·javascript·vue.js
好果不榨汁44 分钟前
qiankun 路由选择不同模式如何书写不同的配置
前端·vue.js
小蜜蜂dry44 分钟前
Fetch 笔记
前端·javascript
拾光拾趣录1 小时前
列表分页中的快速翻页竞态问题
前端·javascript
小old弟1 小时前
vue3,你看setup设计详解,也是个人才
前端
Lefan1 小时前
一文了解什么是Dart
前端·flutter·dart
Patrick_Wilson1 小时前
青苔漫染待客迟
前端·设计模式·架构
写不出来就跑路1 小时前
基于 Vue 3 的智能聊天界面实现:从 UI 到流式响应全解析
前端·vue.js·ui