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相关的安全和隐私泄漏问题还有很多。

此篇结束。

相关推荐
Domain-zhuo1 分钟前
Git常用命令
前端·git·gitee·github·gitea·gitcode
菜根Sec31 分钟前
XSS跨站脚本攻击漏洞练习
前端·xss
m0_7482571837 分钟前
Spring Boot FileUpLoad and Interceptor(文件上传和拦截器,Web入门知识)
前端·spring boot·后端
桃园码工1 小时前
15_HTML5 表单属性 --[HTML5 API 学习之旅]
前端·html5·表单属性
百万蹄蹄向前冲2 小时前
2024不一样的VUE3期末考查
前端·javascript·程序员
轻口味2 小时前
【每日学点鸿蒙知识】AVCodec、SmartPerf工具、web组件加载、监听键盘的显示隐藏、Asset Store Kit
前端·华为·harmonyos
alikami2 小时前
【若依】用 post 请求传 json 格式的数据下载文件
前端·javascript·json
吃杠碰小鸡3 小时前
lodash常用函数
前端·javascript
emoji1111113 小时前
前端对页面数据进行缓存
开发语言·前端·javascript
泰伦闲鱼3 小时前
nestjs:GET REQUEST 缓存问题
服务器·前端·缓存·node.js·nestjs