原稿:语雀 · Cookies · 原目录:Web & 浏览器 › 浏览器渲染 & 前端存储 › Cookies
一直对 cookies 的跨域问题、samesite 等字段混淆,这里整理下
参考链接:
Domain
cookies 的 Domain 指定了哪些主机可以接受 Cookie。如果不指定,默认为 origin,不包含子域名。如果指定了Domain,则包含子域名;不能跨域设置 Cookie,比如阿里域名下的页面把 Domain 设置成百度是无效的:
Set-Cookie: qwerty=219ffwef9w0f; Domain=baidu.com; Path=/; Expires=Wed, 30 Aug 2020 00:00:00 GMT
跨站请求与 CSRF
Cookies 会可能会第三方站点被利用,进行 CSRF:
- 当用户访问 www.a.com 时,该页面会在本地设置 cookies,之后从该站点开启的同站请求都会携带该 cookies,这是安全的情况
- 当 www.a.com 上的某一个恶意链接引导用户点击,在页面 b 上伪造一个在 a 网站上的表单提交请求,该请求中会携带 domain 为 www.a.com 的 cookies;假设网站 a 的敏感操作依赖于验证 cookies 中的 token,则只要链接 b 构造的请求精确,就能利用 cookies 伪装用户进行操作
这种跨站请求时第三方站点携带 cookies 的做法具有风险,服务端可以在 set-cookie 中限定 samesite:
- strict:仅允许第一方请求携带 Cookie,即浏览器将只发送相同站点请求的 Cookie,即当前网页 URL 与请求目标 URL 满足同站
- lax:允许部分第三方跨站请求携带 Cookie
- none:无论是否跨站都会发送 Cookie

跨站≠跨域,Cookies 中的「同站」判断比较宽松:只要两个 URL 的 eTLD+1 相同即可,不需要考虑协议和端口。其中,eTLD 表示有效顶级域名,注册于 Mozilla 维护的公共后缀列表(Public Suffix List)中,例如,.com、.co.uk、.github.io 等。eTLD+1 则表示,有效顶级域名+二级域名,例如 taobao.com 等 |
withCredentials
xhr 的 withCredentials 是前端用来控制是否允许跨域发送/设置 Cookie 的字段,仅在跨域请求有使用意义:当跨域 ajax 请求被发送前,请求头没有设置 xhr.withCredentials=true,那么
- 请求本身不会携带本地同源的 cookies
- 响应的内容也不能为自己的域设置 cookies
因此要想在跨域 ajax 时正确使用 cookies,需要:
- 请求头 withCredentials=true
- 响应头 Access-Control-Allow-Origin 不能为 *,必须明确指定为包含 Origin 的值。
- 响应头 Access-Control-Allow-Credentials 必须为 true