参考文档
https://www.jianshu.com/p/4f3579774a28
https://www.ruanyifeng.com/blog/2019/09/cookie-samesite.html
SameSite场景
跨页面发送cookie是一个常见的需求,但是如果你的后端允许跨域携带Cookie,就有可能被CSRF攻击。
如果想同站的页面发送请求时候携带cookie,跨站的不携带cookie,应该怎么办呢?
chrome和一些浏览器支持了这种能力。
先说明一下什么是同站(SameSite)
同站和同源
同站和同源不一样,同站判断就比较宽松:只要两个 URL 的 eTLD+1 相同即可,不需要考虑协议和端口。其中,eTLD 表示有效顶级域名,注册于 Mozilla 维护的公共后缀列表(Public Suffix List)中,例如,.com、.co.uk、.github.io 等。eTLD+1 则表示,有效顶级域名+二级域名,例如 baidu.com 等。
举几个例子,www.taobao.com 和 www.baidu.com 是跨站,a.baidu.com 和 b.baidu.com是同站,a.github.io 和 b.github.io 是跨站(注意是跨站)。
SameSite规则
后端在set-cookie里面指定SameSite属性,以此来控制三方网站携带cookie的策略。若未指定,Chrome最新版本默认取值是”lax”。
SameSite属性可取值为
- Strict
- Lax
- None
Strict
Strict最为严格,完全禁止第三方 Cookie,跨站点时,任何情况下都不会发送 Cookie。换言之,只有当前网页的 URL 与请求目标一致,才会带上 Cookie。
Lax
Lax规则稍稍放宽,大多数情况也是不发送第三方 Cookie,但是导航到目标网址的 Get 请求除外。
Set-Cookie: CookieName=CookieValue; SameSite=Lax;
导航到目标网址的 GET 请求,只包括三种情况:链接,预加载请求,GET 表单。详见下表。
请求类型 | 示例 | 正常情况 | Lax |
---|---|---|---|
链接 | 发送 Cookie | 发送 Cookie | |
预加载 | 发送 Cookie | 发送 Cookie | |
GET 表单 | 发送 Cookie | 发送 Cookie | |
POST 表单 | 发送 Cookie | 不发送 | |
iframe | 发送 Cookie | 不发送 | |
AJAX | $.get(“…”) | 发送 Cookie | 不发送 |
Image | 发送 Cookie | 不发送 |
设置了Strict或Lax以后,基本就杜绝了 CSRF 攻击。当然,前提是用户浏览器支持 SameSite 属性。
None
若想允许非同站访问接口时候携带cookie,网站可以选择显式关闭SameSite属性,将其设为None。不过,前提是必须同时设置Secure属性(Cookie 只能通过 HTTPS 协议发送),否则无效。