SameSite - 了解篇

5,425 阅读5分钟

最近因为Chrome升级到80以后,带来了一些新的问题,需要考虑到其带来的影响,其中之一是关于SameSite默认值的改变,本次计划用两次来说明SameSite以及如何进行相关的升级和兼容

1. 基本概念

1.1 SameSite是什么

MDN上有比较完整的描述:

SameSite cookies let servers require that a cookie shouldn't be sent with cross-site (where Site is defined by the registrable domain) requests, which provides some protection against cross-site request forgery attacks (CSRF).

翻译过来,SameSite的作用就是在请求的时候来判断cookie可以跨站传递(和跨域概念有所不同,虽然都是cross-site,自己一开始理解的是跨域,直到得到了同事的提醒才知道这里是指跨站),举个简单的例子,假如现在有两个站点www.a.comwww.b.com,如果前者中引用了后者请求,那么在发送请求的时候,是否会携带后者的cookie到后者的服务器呢?SameSite的作用其实就是对该情况进行描述。

其中对于跨站的理解,那么需要判别同一站点两个地址是否是同一站点,引用一下同事的相关说明:

在绝大部分的情况下,我们可以将同一站点简单理解为常说的 二级域名,所以,samesite所约束的同一站点就是指:同一个二级域名下的各个子域名间的资源属于同一个站点。当然,跨站点就是指不是同一站点的意思。

浏览器判断是否跨站,是利用了Public Suffix List的策略,该策略可以认为是浏览器维护了一系列站点的地址,例如:Mozilla 很久之前维护的这个域名后缀列表,通过规则匹配,则符合同一规则的地址将认为是同一站点,具体详细内容可参见紫云飞:关于SameSite的博客

1.2 SameSite如何使用

目前SameSite有三个常用的值Strict, Lax, None,他们的作用是对跨站请求的cookie做不同程度的限制,而根据请求的不同,其对应关系如下:

可以简单的认为:

设置为Strict以后,跨站点就不会再传递该cookie

    document.cookie = 'key=value;SameSite=Strict'

设置为Lax以后,会限制部分请求cookie的传递

    document.cookie = 'key=value;SameSite=Lax'

不对cookie做设置,会在跨站点情况下发送cookie

    document.cookie = 'key=value;'

常规模式下以前只有这三种情况,但是SameSite还可以设置为None,且从Chrome从76版本开始,开始对设置为None必须和Secure配合使用,表示为

    document.cookie = 'key=value;SameSite=None;Secure'

由于使用了Secure,则当前站点必须使用https的安全链接

1.3 为什么本次需要升级

因为从Chrome 80开始,默认会对cookie设置SameSite=Lax,ChromeLab对此有比较清楚的说明:地址,目前项目中大部分cookie是没有设置任何的SameSite属性,所以可能出现跨站cookie无法传递的情况,需要对这部分内容进行处理,否则,可能出现cookie无法传递导致类似登陆失败问题。

当然,我们可以自行开启和关闭浏览器对于该默认值的设定

chrome://flags/#same-site-by-default-cookies

也可以设置在SameSite=None的时候,必须使用https的请求

chrome://flags/#cookies-without-same-site-must-be-secure

1.4 其他

1.4.1 跨站和跨域的区别

补充说一下自己认为跨站和跨域的区别,在做测试的时候,最开始认为是跨域,所以使用两个端口(8080,8081)进行尝试,结果发现不论如何设置,两个站点cookie的传递都是可以正常发起;

之后误打误撞的使用了127.0.0.1和本地局域网IP(172.168.0.xxx)进行尝试,发现居然能使用SameSite的设置了,所以,至少从这个层面上来说,跨域是指对于协议(protcol),域名(host),端口(port)的不同,可能自己的理解也存在偏差,这里如果有更好的理解可以随时私信

2. 具体测试案例

具体例子可参见Github,例子主要是根据了Chrome官方的测试方案,进行了摸索本地如何验证该特性,测试步骤主要包括以下特性验证:

1.使用Chrome浏览器的默认设置,请求结果如何;

2.开启相关Chrome的设置,请求结果如何;

3.开启Chrome设置后,设置SameSite=NoneSecure,以及开启https请求后,结果如何

ps: 本次测试使用Chrome80版本

几个注意的细节:

2.1 如何开启https服务

网上存在很多相关资料,所以这里不赘述,具体可参见github的例子

2.2 如何确定cookie是否已经设置相关属性

打开Chrome控制台,切换到Application,查看cookie,会发现如果配置成功,那么cookie最后一列的SameSite会设置相关属性

2.3 关于给cookie增加SameSite属性

通过尝试可以发现cookie增加SameSite属性是针对单个cookie值进行的追加

2.4 开启https后访问地址

开启https访问地址可以发现cookie中增加了SameSite=None的cookie

3. 参考

Github-Chrome Github SameSite

CSDN-cookie 的 SameSite 属性

Though cookie

掘金-跨站请求已死