写这篇文章的初衷是我在项目当中遇到了关于SameSite属性默认值改变引起的bug,突然发现网站中嵌入的iframe无法登录。找了一些资料,了解到有可能是由SameSite属性默认值改为Lax造成的,但是a.demo.com 和 b.demo.com 是同站啊?为什么会出现这种问题呢?
本站网站:a.demo.com
嵌入网站:b.demo.com
后来,参考英文资料,发现跨协议(http、https)也被划分为跨站行为。
由于补了一些这方面的知识,为了后面忘记,这里记录一下吧。
cookie我知道,但是什么是第三方cookie?
这里直接举个例子,我们打开天猫的网站,看他的控制台application中的cookie:
观察上图,我们可以发现,在天猫的网站cookie下,不只是有.tmall.com
下的cookie,还有.taobao.com
下的很多cookie。
当我们在访问www.tmall.com/ 的时候,将注册在.tmall.com
域名下的cookie叫做第一方cookie,而不是这个域下的cookie称为第三方cookie。
但是,我从来没有在电脑上访问过taobao.com啊?为什么他会出现在我的cookie中呢?
第三方cookie是怎么得到的?
继续上面的例子,.taobao.com
下的cookie是如何写入.tmall.com
下的?
—通过跨站发送请求
我们在打开天猫网站的时候,就向taobao.com发送了一些请求,这些请求在响应头部中通过set-cookie字段向本站注入了很多cookie(来自.taobao.com),当我们登录天猫之后,由于天猫与淘宝用的是同一套登录系统,账户信息也会保存在.taobao.com域名下的cookie中。这样,当我们打开淘宝之后,这些.taobao.com域名下的cookie就会携带过去,自然就可以自动登录。
第三方cookie用在哪里
- 前端埋点
我在项目中的network中发现了一个log.gif
的请求,我猜这是用来埋点的。
埋点是如何实现的?
当你访问主站时,会向埋点服务器发送请求,会set-cookie一个标识,表示用户的唯一值ID。此后,用户的点击、浏览行为都会以请求的方式携带此cookie发送给埋点自己的服务器,从而实现记录和监控每个用户行为的功能。
这个埋点服务器会用自己的域名去注册cookie,这个cookie对于主站来说就是第三方cookie。
- 用cookie”做广告“
- jd.com是一个购物网站
- blog.com是一个博客网站
- ad.com是一个广告服务商
- ad.com可以帮助jd.com在blog.com博客网站上做广告
- 当用户访问blog.com的时候,会加载ad.com广告服务商的js脚本(用于广告加载、记录用户的点击和浏览广告的行为)。此脚本实现的请求可以使得ad.com向博客中注入自己域名下的cookie,此后每次用户点击广告等行为的请求都会携带该cookie发给ad.com的服务器。
- 当用户跳转到jd.com,也会携带证明用户身份的cookie。此后用户在jd.com网站上的购买行为也会被发送到ad.com的服务器。
- 通过唯一ID将用户在blog.com的广告浏览、点击数据与用户在jd.com下单数据合并分析,计算广告的转化率
上述过程中可以实现计算广告转化率的原因就是:这个表明用户身份唯一性的cookie将用户在blog.com的账户和用户在ad.com的账户建立了唯一性的联系。
浏览器之前是如何处理第三方cookie的
之前,浏览器cookie的SameSite属性默认是None,意思是允许所有的跨站行为携带cookie。(携带满足其域名规则下的cookie)
简单来说:允许set-cookie其他域下的cookie,并且在请求时可以携带这些第三方cookie到其他网站。
现在浏览器是如何处理第三方cookie的
浏览器cookie的SameSite属性默认是Lax,允许部分跨站行为携带cookie,具体参照下表:
跨协议行为算跨站吗
跨协议,字面意义上就是不同的协议之间的交户。比如http与https之间链接的跳转就是跨协议行为。
跨协议行为也被列入到跨站行为,所以也会受SameSite属性的影响。
协议上的同站
“同站”的定义现在正向包含URL上的协议(http\https等)演变,因此同一个站点的不同协议版本(https和http)之间的链接现在算作为跨站请求。当然,可以将http升级到https来避免这些问题,或者继续阅读以获取更多关于SameSite的详细信息。
之前我们认为的同站是有效顶级域名+二级域名相同,而协议上的同站是有效顶级域名+二级域名+协议相同。
- 关键术语:这意味着一个站点不安全的http版本,例如website.example 和该站点的安全版本website.example ,现在是跨站。
好消息是:如果你已经将网站完全更新到了https,你不用担心任何问题,这个变化不会对你的网站有任何的影响。
如果您尚未完全升级您的网站,则应着重考虑一下这个问题。 如果在某些情况下您的站点访问者会在HTTP和HTTPS之间切换,下面概述了一些常见情况以及与之相关的SameSite Cookie行为。
警告:chrome的长期计划是完全禁用第三方cookie,以保护用户的隐私。在某个cookie上设置SameSite=None; Secure
,来允许跨协议请求,只是一种代替https迁移的临时方案。
谷歌将SameSite=Lax作为cookie SameSite属性的默认值的主要原因是为了防止跨站点请求伪造(CSRF)。然而,不安全的http请求仍然会为网络攻击者提供篡改cookie的机会。在协议之间创建额外的跨站边界可以进一步的防御这些攻击。
常见的跨协议场景
在下面所有的场景当中,所有的URL都具有相同的有效顶级域名+二级域名,但是它们的协议却不相同,site.example vs. site.example
,被称作为跨协议。
- 导航
在站点的跨协议之间的导航(例如,从http://site.example跳转到https://site.example),之前SameSite=Strict的时候是允许发送cookie的。但是现在是不允许的,因为现在被认为是跨站链接。
2.加载子资源
子资源包含图片、iframe和网络请求(XHR、fetch等)。
之前,在页面上加载跨协议子资源,在 SameSite=Strict或者SameSite=Lax的情况下是允许携带cookie的。现在,这种情况与任何跨站或者第三方的子资源一样,在 SameSite=Strict或者SameSite=Lax的情况下,cookie会被阻止。
此外,即使浏览器允许在安全的页面上加载不安全的子资源,所有的cookie也会被当作第三方或者跨站cookies,不被发送。
- POST 表单
之前,在跨协议版本的站点上发送post请求,在 SameSite=Strict或者SameSite=Lax的情况下是允许的。现在,这种情况被视作为跨站请求,只有在SameSite=None的时候才会被允许。
与子资源一样,如果请求来自安全链接,例如 HTTPS,到不安全的 HTTP,所有上下文中的Cookie都会被阻止,因为该cookie被视为跨站或者第三方cookie。
警告:最好的解决方案是确保表单页面和目标链接都属于安全链接(例如HTTPS)。 如果用户要在表单中输入任何敏感信息,保证这一点尤其重要。
再回过头来看,开头的bug就是因为我们在http中内嵌了https iframe,在SameSite=Lax的情况下,是不允许携带cookie的,因此导致登录不成功。
总结:
set-cookie是在某一个域名下设置cookie,但是是否允许携带,就是SameSite说了算。
参考文章: