好久不见。
又来了
- 好久好久好久不见。
- 但有时候我想想,人还是得学习。
- 坚持真的是个有益的能力。
同源策略(主讲Chrome 91的坑)
简要介绍
- 同源(same-origin):那就是常见的三个元素,协议,主机名,端口(scheme, hostname, port)都得一样。
- 同站(same-site):有效的顶级域名+顶级域名前的部分,都得一样。
Same Origin
上图中的 scheme, hose name, port 都相同则为 same origin ,否则为 cross origin。
https://www.example.com:443 | https://www.evil.com:443 | cross-origin: different domains |
https://www.example.com:443 | https://example.com:443 | cross-origin: different subdomains |
https://www.example.com:443 | https://login.example.com:443 | cross-origin: different subdomains |
https://www.example.com:443 | http://www.example.com:443 | cross-origin: different schemes |
https://www.example.com:443 | https://www.example.com:80 | cross-origin: different ports |
https://www.example.com:443 | https://www.example.com:443 | same-origin: exact match |
https://www.example.com:443 | https://www.example.com | same-origin: implicit port number (443) matches |
Same Site
上图中的 eTLD+1 相同则为 same site ,否则为 cross site。
https://www.example.com:443 | https://www.evil.com:443 | cross-site: different domains |
https://www.example.com:443 | https://login.example.com:443 | same-site: different subdomains don't matter |
https://www.example.com:443 | http://www.example.com:443 | same-site: different schemes don't matter |
https://www.example.com:443 | https://www.example.com:80 | same-site: different ports don't matter |
https://www.example.com:443 | https://www.example.com:443 | same-site: exact match |
https://www.example.com:443 | https://www.example.com | same-site: ports don't matter |
Schemeful Same Site
上图中的 scheme, eTLD+1 都相同则为 schemeful same site ,否则为 cross site。
https://www.example.com:443 | https://www.evil.com:443 | cross-site: different domains |
https://www.example.com:443 | https://login.example.com:443 | schemeful same-site: different subdomains don't matter |
https://www.example.com:443 | http://www.example.com:443 | cross-site: different schemes |
https://www.example.com:443 | https://www.example.com:80 | schemeful same-site: different ports don't matter |
https://www.example.com:443 | https://www.example.com:443 | schemeful same-site: exact match |
https://www.example.com:443 | https://www.example.com | schemeful same-site: ports don't matter |
如何查看
Chrome 的 Network 面板中查看 http 请求头中的 Sec-Fetch-Site 字段值。
该字段的值有四个:
- cross-site
- same-site
- same-origin
- none
其中命中了 cross-site 和 cross-origin,则命中 Chrome 的同源同站策略,Chrome 会做出认为安全的访问限制,比如 Cookie 是带不过去了。
解决方案
- 就只能全部同源同站,这样页面和接口请求永远安全。
- 登录态的方案不采用 Cookie,采用 Token 或者其他安全方案。
- 同事还提供了一个方案,nginx 配置代理后端接口请求,统一走页面域名。
我真的是被 Chrome 一直吊打,80版本的时候就不放过我,91版本依然有老项目命中。
我一直也是 get 不到这个限制的意义,因为我觉得随便在headers约定一个字段就越过了这个限制,但有的同事解释说主要是为了防止第三方,比如统计工具之类的,并不是防我。。。
我的 case 稍微有点复杂,简单描述一下,提供使用。公司的老项目,不似现在的脚手架可以做请求代理,但是部署到环境上的页面和接口请求又是同站的,所以只需要解决本地开发问题。
- 页面和接口请求都在 host 配置同站的域名
- 同为 http 请求不会命中 Schemeful Same Site,那如果命中了,就在 中禁用 Schemeful Same-Site 选项,重启即可。
以上是91版本的坑。80之后91之前的版本,是没有这么严格的,可以在 chrome://flags/ 中禁用 same-site-by-default-cookies 及 cookies-without-same-site-must-be-secure 即可。但这些禁用也仅限开发者使用,非长久之计。
没了,还想再记录一下跨域的问题。虽然都是很常见的问题。
参考
- Understanding "same-site" and "same-origin"
- W3 / The Sec-Fetch-Site HTTP Request Header
- The Chromium Projects / Portals
- chrome://flags/
好记性不如烂笔头。