大家好,我是年年!
今天介绍的是三方cookie相关的内容,本文会讲清:
- 什么是三方cookie?
- same-site的变化是什么,对我们的业务有什么影响?
- 为什么有了same-site,还需要same-party?
什么是三方cookie
三方指的是非同站,这个同站和同源协议中的源origin不同,它的要求更宽松。
同源协议中的源是由「协议+域名+端口」三者一起定义的,有一个不同就不算同源,而同站只受域名的约束,并且还不要求一模一样——只要「有效顶级域名+二级域名」相同,都算同站。
有效顶级域名是由Mozilla维护的一份表格,其中包括.com、.co.uk、.github.io等。所以ai.taobao.com和www.taobao.com是同站的,因为它们的顶级域名(.com)+二级域名(.taobao)相同。
现在知道了什么是站,就可以很简单区分了:
打开开发者工具的application,domain一列中显示和当前域名不同的就是三方cookie。
如何携带三方cookie
cookie的携带是浏览器自动的操作,规则是「不认来源,只看目的」,下面会讲清这句话的意思。
cookie下发
首先,需要先了解cookie的下发,服务端会将其下发到浏览器,方法是通过响应头中的set-cookie字段。
里面还包括一些配置属性,关键的是其中的domain。
domain
指定cookie未来使用时,可以被携带到哪些域名。其值可以设置为当前服务端的父级域名或其本身,比如ai.taobao.com设置的cookie的domain可以为.taobao.com,所设置值的所有子域名都可以使用,比如www.taobao.com。
如果不设置,会默认为当前域名ai.taobao.com,并且只有自己可以使用,子域名sub.ai.taobao.com都不能使用,适用范围就小了很多,所以一般都会设置。
但是不能设置为跨站点的.baidu.com,也不能是顶级域名.com。
其余的属性还有这些:
1.path:指定cookie未来使用时,可以被携带到合法域名的哪些URI。和domain很像,也只能设置为当前路径的父级路径或其本身,设置值的所有子路径都可以访问。
2.expire/max-age: 指定cookie的有效期,其中expire是一个绝对时间,max-age是相对时间,单位是秒,两者同时存在时,max-age优先级更高;如果两者都没有,则为会话级别的cookie,即用户关闭浏览器时失效。
Set-Cookie: id=nian; Expires=Wed, 30 Aug 2022 00:00:00 GMT; Max-Age=3600
3.secure:只能在HTTPS环境中被下发以及携带。
4.http-only:禁止客户端脚本通过 document.cookie 获取 cookie,避免 XSS 攻击。
5.还有下面会重点讲解的same-site和same-party。
Cookie携带
上面提到,cookie的domain字段很关键,它规定请求哪些域名才会携带,注意,这里指的是请求目的地的域名。
举个例子,首先我通过响应头在浏览器中设置了一个cookie,domain是.a.com。
set-cookie: id=nian; domain=.a.com;
现在有三个请求:
- 网页www.a.com/index.html的前端页面,去请求接口www.b.com/api。
- 网页www.b.com/index.html的前端页面,去请求接口www.a.com/api。
- 网页www.a.com/index.html的前端页面,去请求接口www.a.com/api。
有点绕,可以暂停思考10秒,哪个请求会带上之前设置的cookie呢?
答案是2、3都会带上cookie,因为cookie的取用规则是去看请求的目的地,2、3请求的都是www.a.com/api命中domain=.a.com规则。
这就是「不认来源,只看目的」的意思,不管请求来源是哪里,只要请求的目的是a站,cookie都会携带上。
通过这个案例也可以再回顾一下:3的这种情况的叫第一方cookie,2的这种情况叫第三方cookie。
限制三方cookie的携带
「不认来源,只看目的」规矩在2020年开始被打破,这种变化体现在浏览器将same-site:lax设置为默认属性。
chrome操作比较平缓,目前可以手动设置same-site:none恢复之前规则。
但在safari中如果这样设置,会被当作same-site:strict。
可以看到,在safari中使用的全是第一方cookie,直观的体验就是在天猫登录完,打开淘宝,还需要再登录一次。
也就是说现在cookie的取用是「既看来源,又看目的」了。
SameSite
上面提到的same-site是cookie的一个属性,它制约第三方cookie的携带,其值有三个none、strict、lax。
- strict代表完全禁止三方cookie,这是最严格防护,可以避免被CSRF攻击,但缺点也很明显,像天猫、淘宝这种同属一个主体运营的网站不得不重复登录。
- none代表完全不做限制,即之前「不认来源,只看目的」的cookie取用原则。
- Lax则是折中,在某些情况下会限制三方cookie的携带,某些情况又放行,这也是浏览器的默认值(包括safari)。
在safari,same-site的默认值是lax,如果把它设置为same-site:none,会适得其反,被当作strict处理。
SameSite的修改
可以这么理解,浏览器将same-site的默认值从none调整到了lax。
same-site:lax的具体规则如下:
而在这之前是会全部发送的。
SameSite修改带来的影响
像a链接这种,没有受到影响,依旧会带上三方cookie,这样可以保证从百度搜索中打开淘宝,是有登录状态的。
但是对大部分业务的影响是巨大的,比如监控埋点系统。
埋点监控SDK是用图片的src去做请求的发送的,从上面的表格可知,变成lax后默认不发送了,这时用户的身份便无法确认,UV也没法统计了。
为什么埋点监控用会图片的src,之前详细写过一篇文章,戳这里。
为了解决这些问题,大部分公司目前的解决方案是设置same-site:none并且配合secure,就可以像以往一样,继续携带第三方cookie。
但这不是版本答案。
SameParty
上面说到,为了绕开浏览器对三方cookie的限制,保障业务的正常,我们的解决方式是把same-site又设置回none。
但这不是长久之策,一来,浏览器把same-site的默认值从从none调整到lax可以避免CSRF攻击,保障安全,可我们为了业务正常运行,却又走了回头路;二来,chrome承诺2022年,也就是今年,会全面禁用三方cookie,届时和在safari一样,我们没法再用这种方法去hack。
如果我们不想使用same-site:none,或者说,未来用不了这种方式了,same-party将是我们的唯一选择。
什么是 SameParty
继续沿用阿里系的例子,same-party可以把.taobao.com、.tmall.com和.alimama.com三个站合起来,它们设置的cookie在这个集合内部不会被当作第三方cookie对待。
首先需要定义First-Party集合:在.taobao.com、.tmall.com和.alimama.com三个站的服务器下都加一个配置文件,放在/.well-know/目录下,命名为first-party-set。
其中一个是“组长”,暂定为.taobao.com,在它的的服务器下写入。
// /.well-know/first-party-set
{
"owner": ".taobao.com",
"members": [".tmall.com", ".alimama.com"]
}
另外两个是组员:
// /.well-know/first-party-set
{
"owner": ".taobao.com",
}
并且,在下发cookie时,需要注明same-party属性:
Set-Cookie: id=nian; SameParty; Secure; SameSite=Lax; domain=.taobao.com
这样,我们打开.tmall.com的网站,向.taobao.com发起AJAX请求,都会带上这个cookie,即使当前的same-site属性是lax,因为这集合中的三个域名都会被当作一个站对待,也就是说,在浏览器眼中,这个cookie现在就是第一方cookie。
而不在集合中的baidu.com发起的AJAX请求则不会带上。
需要注意的是,使用same-party属性时,必须要同时使用https(secure属性),并且same-site不能是strict。
结语
对三方cookie的限制一是为了浏览器安全,但在国外推动的更重要原因是个人的隐私安全。但不论是出于什么目的,这种改变都会对当前的业务架构造成很大的影响。
same-site:lax变成默认是一个暂时的预警,它限制了特定场景下的第三方cookie使用。目前处于比较柔和的过渡期,因为在大部分浏览器中,我们可以简单地将它调整回same-site:none来解除这些限制,和以前一样畅通无阻。
但未来这项限制终将无法脱下,same-party才是版本答案,有了它,我们可以灵活定义哪些站属于业务意义上的“第一方”,哪些才是我们想要的“第三方”。