Cookie是便于向网站添加持久化状态的方式之一。随着时间推移,它们的能力得到了扩展和进化,也造成了很多历史遗留问题。为了解决这个问题,浏览器产商(包括Chrome,Firefox,和Edge)改变了他们的处理逻辑以加强个人隐私的默认配置。

每一个cookie都是拥有一些为了控制何时何处被使用的键值对。你可能已经通过这些属性去设置过期时间或者指明当前cookie只能在https协议下传输。服务器通过在响应中携带Set-Cookie头来设置cookie。想要了解详细信息,可以深入阅读RFC6265bis,现在只是快速的回顾一下。

现在假设你的博客网站需要向用户推送一个“最新内容”的提示。用户可能会取消这个提示并且一段时间内他们也不会再看这个提示。你可以将这种喜好设置在一个cookie中,给它设置一个月(2,600,000 seconds)后到期,并且只能在HTTPS协议下传输。这个头部可能看起来像这样:

  1. Set-Cookie: promo_shown=1; Max-Age=2600000; Secure



服务器通过Set-Cookie头来设置cookie

当你的读者正在访问一个做了上面这些设置的页面,进一步说他们正在使用HTTPS进行连接并且这个cookie存续时间小于一个月,那么他们的浏览器就会请求里携带如下的头部:

  1. Cookie: promo_shown=1



浏览器通过Cookie头回传cookie

在javascript中通过使用document.cookie可以读取或者添加站点的cookie。对document.cookie进行赋值操作将会覆盖对应键的cookie。举个例子,尝试在你的浏览器javascript console中输入以下语句:

  1. > document.cookie = "promo_shown=1; Max-Age=2600000; Secure"
  2. < "promo_shown=1; Max-Age=2600000; Secure"

读取document.cookie将会打印出所有能够在当前环境中获取到的cookie,每个cookie通过一个分号分隔

  1. > document.cookie;
  2. < "promo_shown=1; color_theme=peachpuff; sidebar_loc=left"



JavaScript中可以通过使用document.cookie获取cookie

如果你尝试在一些流行的站点上读取cookie,你会明显发现它们中大多数设置了超过3个cookie。在大多数场景下,这些cookie将会根据一系列因素携带在对应域名的请求中。对于你的用户来说,一般上行带宽一般比下行带宽拥有更多的限制,所以将大量携带在cookie对外的请求上将会导致将会导致请求获取第一个字节的延迟。为了合理控制设置的cookie数量。通过设置Max-Age属性来帮助保证cookie在不需要的时候及时被清除掉。

什么是自有和第三方cookie?

重新访问前面一系列站点,很可能会发现有些cookie会在很多不同域名下出现,不仅仅是当前正在访问站点域名。当前站点域名(显示在浏览器地址栏里面的域名),被称为自有域名。同样的,那些来自当前站点外域名的cookie被称为第三方域名。这只是相对用户的角度并不是一个绝对的标签,同样的cookie既可能是自有的也可能是第三方的,取决于用户当前访问的站点。



一个页面上的cookie可能来自多个不同域名

继续前面的例子,假设你的一篇博客当中有一张极其可爱的小猫图片,这张图片存储在/blog/img/amazing-cat.png下。由于这张图片太可爱了,其他人在他们的网站上直接使用了它。如果一个用户访问过你的博客将会有promo_shown cookie,当他在其他网站上看到这张直接被引用的图片时,图片的请求将会携带这个cookie。这并不是对任何人都特别有用,因为promo_shown在其他人的网站上并不是对任何请求都有用,这样只会增加请求的负载。

如果这并不是有意达成的效果,那在什么情况下你需要这样了。这是一种允许在第三方站点环境上保持会话状态的机制。例如,如果在你的站点页面上添加了一个YouTube video,那么访问者将会在播放器中看到一个"watch later"的操作项。如果访问者已经登陆了YouTube,第三方cookie将会使得用户通过一步点击"watch later"按钮收藏这个视频到YouTube供后续观看,而不需要提醒他们登陆YouTube或者离开当前站点并跳转到YouTube。



在第三方环境下访问不同的页面cookie将被传输

万维网文化属性之一是开放共识。这使得许多人创造自己的内容和应用程序成为可能。然而这也带来了一些安全和隐私风险。跨站请求伪造攻击(Cross-site request forgery attack-csrf)制造依赖于那些cookie将会被携带在针对指定域名的请求中,而不论这些请求具体由谁触发。举个例子,当你访问了evil.example并且它可以触发your-blog.example的请求,那么浏览器将会很乐意携带上关联的cookie。如果你的博客对这些请求的验证不够仔细那么evil.example可以触发删除和添加内容的任何操作。

用户现在更加清醒的意识到cookie怎样被用来跟踪他们在不同页面的活动轨迹。然而直到现在仍然没有一种明确的方式表明对cookie本来用意。你的promo_showncookie本应该只被用在自有站点环境下,而嵌入到第三方站点的组件所携带的会话cookie是被用来保持会话状态。

使用SameSite明确表明cookie的用途

SameSite属性的引入(定义在RFC6265bis)允许你表明你的cookie被用在第三方或者自己的站点环境下。明白站点的确切意义将会大有裨益。站点是域名后缀和它前面部分的混合。例如,www.web.dev域名站点是web.dev域名站点的一部分。

关键词same-site

如果用户在www.web.dev发起了一个向static.web.dev的图片请求这是一个same-site请求。

public suffix list定义了这些,不仅是像.com这样的顶级域名也包括像github.io这样的域名。这使得your-project.githubmy-project.github被认为为不同的站点。

关键词cross-site

如果用户在your-project.github.io站点发起了一个向my-project.github.io的请求,这是一个cross-site请求。

在cookkie中引入SameSite属性三种控制这种行为的方式。你可以不指定指定这个属性,或者通过使用StrictLax来限制cookie只在same-site请求下携带。

如果你设置SameSite属性为Strict,那么你的cookie将会只在自有环境下发送。在用户看来,那个cookie只会在匹配当前显示在地址栏的站点时才会被发送。所以,假设Promo_showncookie如下设置:

  1. Set-Cookie: promo_shown=1; SameSite=Strict

那么当你的用户在你的站点上是,cookie将会如预期被发送。然而当从一个指向你站点的引用链接,详细地说当从另一个站点或者从通过一个朋友发给你的一个链接,在初始请求里并不会这个cookie并不会被发送。当你拥有一些关联后置于初始导航你站点功能的cookie的情形下,例如修改密码或者下订单的情形下,这是极其有用的,但是对于promo_shown这个功能限制太多。如果你的用户通过链接进入你的站点,他们希望cookie能被发送,这样他们的设置能够生效。

当你的用户初始导航到你的网站上时cookie将会被发送,这就是SameSite=Lax的使用场景。让我们继续回顾那个引用小猫图片的例子,那个例子中其他站点正在引用你的内容。他们直接使用你的小猫图片并且提供了一个指向你的原始文章的链接地址。

  1. <p>Look at this amazing cat!</p>
  2. <img src="https://blog.example/blog/img/amazing-cat.png" />
  3. <p>Read the <a href="https://blog.example/blog/cat.html">article</a>.</p>

cookie这样设置:

  1. Set-Cookie: promo_shown=1; SameSite=Lax

当浏览者在其他人的博客上请求amzing-cat.png,cookie将不会被发送。然而当读者通过一个点击一个指向你站点cat.html的链接时,cookie将会被发送。这样的话,使得Lax成为设置影响网站外观cookie的好选择而Strict将会对用户那些关联到当前操作的cookie极其有用。

注意

StrictLax对于你的站点安全都不是一个完整的解决方案。cookie将会作为用户输入的一部分,你需要像对待其他用户输入一样。意味着,需要对这些输入进行脱敏和验证。绝对不要将服务端的重要数据存储在cookie中。

最后还有一个不设置这个值的默认方式,那么cookie将会在所有上下文情形下被发送。在最新的RFC6265bis草案中这种方式被SameSite=None这个新值明确表达。这表明你可以通过设置SameSite=None来明确表明你希望cookie在所有第三方上下文环境下被发送。

!(None Lax Strict)[https://webdev.imgix.net/samesite-cookies-explained/samesite-none-lax-strict.png]

通过NoneLaxStrict来明确表明cookie的使用上下文

★ 如果你提供了供其他网站使用的服务,例如嵌入式组件、嵌入式多媒体内容、联合程序、广告、跨站登陆那么你需要使用None来明确表明的意图。

未设置SameSite属性默认行为的变化

尽管SameSite属性得到广泛支持,很不幸的是并没有很广泛的被开发者使用。cookie在所有地方都会被发送的开放默认行为使得所有场景都能正常工作,但是这样提高了用户受到CSRF和意外信息泄漏的风险指数。为了号召开发者明确表明他们的意图并且提供用户更高的安全使用体验,IETF发布了一个提议,Incrementally Better Cookies提供了两项关键改进:

  • 那么没有设置SameSite属性的cookie将等同设置了SameSite=Lax
  • cookie设置SameSite=None必须同时设置Secure,这意味着需要在更安全的环境下传输。

Chrome在84版本实现了以上默认行为。Firefox在69版本可以测试使用,并且未来会加入默认配置中。为了在Firefox中测试这些行为,打开about:config然后network.cookie.sameSite.laxByDefault。Edge也计划改变其默认行为。

原文

https://web.dev/samesite-cookies-explained/

samesite-cookie详解(译文)的更多相关文章

  1. Cookie 详解以及实现一个 cookie 操作库

    Cookie 详解以及实现一个 cookie 操作库 cookie 在前端有着大量的应用,但有时我们对它还是一知半解.下面来看看它的一些具体的用法 Set-Cookie 服务器通过设置响应头来设置客户 ...

  2. Cookie的使用、Cookie详解、HTTP cookies 详解、获取cookie的方法、客户端获取Cookie、深入解析cookie

    Cookie是指某些网站为了辨别用户身份.进行session跟踪而存储在用户本地终端上的数据(通常经过加密),比如说有些网站需要登录才能访问某个页面,在登录之前,你想抓取某个页面内容是不允许的.那么我 ...

  3. cookie详解

    一.cookie详解 (1)设置cookie 每个cookie都是一个名/值对,可以把下面这样一个字符串赋值给document.cookie: document.cookie="userId ...

  4. ASP.NET 操作Cookie详解 增加,修改,删除

    ASP.NET 操作Cookie详解 增加,修改,删除 Cookie,有时也用其复数形式Cookies,指某些网站为了辨别用户身份而储存在用户本地终端上的数据(通常经过加密).定义于RFC2109.它 ...

  5. 网络基础 cookie详解

    cookie详解 by:授客 QQ:1033553122 cookie干嘛用的? 参见文章http 会话(session)详解: 网络基础 http 会话(session)详解   cookie分类 ...

  6. cookie详解(含vue-cookie)

    今天看到一篇cookie的文章,写的特别详细,感谢 晚晴幽草轩 的分享,原文链接http://mp.weixin.qq.com/s/NXrH7R8y2Dqxs9Ekm0u33w 原文如下,记录到此供以 ...

  7. Session和Cookie详解(1)

    面试常问的有关session和cookie的问题: 1.session在分布式环境下怎么解决 2.集群下如何保证session踩中 3.cookie的大小 4.服务器怎么识别一个用户的 5.sessi ...

  8. JavaWeb Cookie详解

    代码地址如下:http://www.demodashi.com/demo/12713.html Cookie的由来 首先我们需要介绍一下,在Web开发过程中为什么会引入Cookie.我们知道Http协 ...

  9. [转]Cookie详解

    从事 Web 开发已有近17个月:在学以致用的工作学习里,对于不怎么使用的部分,多少有些雾里探花的窘迫感-差不多是了解一二,然而又非真切的明晰:这就使得再用的时候,总要去再搜索一番:如此颇为难受,倒不 ...

  10. Java web Cookie详解(持久化+原理详解+共享问题+设置中文+发送多个Cookie)

    Java web Cookie详解 啥是cookie? 查询有道词典得: web和饼干有啥关系? 这个谜底等等来为大家揭晓 会话技术 web中的会话技术类似于生活中两个人聊天,不过web中的会话指的是 ...

随机推荐

  1. [LeetCode]1083. 销售分析 II(Mysql,having+if)

    题目 编写一个 SQL 查询,查询购买了 S8 手机却没有购买 iPhone 的买家. 题解 使用having + sum+if,而不是自查询. 代码 # Write your MySQL query ...

  2. [LeetCode]322. 零钱兑换(DP)

    题目 给定不同面额的硬币 coins 和一个总金额 amount.编写一个函数来计算可以凑成总金额所需的最少的硬币个数.如果没有任何一种硬币组合能组成总金额,返回 -1. 示例 1: 输入: coin ...

  3. 仿苏宁移动web页面 自适应 rem&less

    index.html <!DOCTYPE html> <html lang="en"> <head> <meta charset=&quo ...

  4. nginx如何写日志

    写日志函数为ngx_log_error_core,位于src/core/ngx_log.c:89行核心代码如下:while (log) { if (log->log_level < lev ...

  5. 虚拟机栈(Java Stack)基础知识

    虚拟机栈即是程序运行时的单位,而堆是数据存储的单位.换句话说,栈解决的是程序运行的问题,即程序如何执行,如何处理数据,而堆是解决数据的存储问题,数据存在哪,放在哪 虚拟机栈细节如下图所示,其中当前栈帧 ...

  6. 栈帧的内部结构--操作数栈(Opreand Stack)

    每个栈帧中包含: 局部变量表(Local Variables) 操作数栈(Opreand Stack) 或表达式栈 动态链接 (Dynamic Linking) (或指向运行时常量的方法引用) 动态返 ...

  7. Nodejs-原型链污染

    原型链污染 javascript 原型链 在javascript中,继承的整个过程就称为该类的原型链. 每个对象的都有一个指向他的原型(prototype)的内部链接,这个原型对象又有它自己的原型,一 ...

  8. 【PowerQuery】做了一万遍的工资条

    前面已经了解了Excel.VBA.Python实现工资条,今天尝试用PQ做一遍 做之前迷惑了很久,如何能自定义长度 Table有Repeat函数,但是List没有.看来另外想办法 一步步接近目标  请 ...

  9. 简单两步实现Android app 本地设置信息的保存与调用

    调用值 SharedPreferences preferences = this.getSharedPreferences("mspda", 0); lblVer.setText( ...

  10. C#方法Extra

    C#方法Extra 上次说的只是方法的一些基本东西,今天讲讲重载和 Lambda 表达式. 重载 方法的重载(overload)指的是同一个名字的方法,有着不一样的方法签名(method signat ...