近期在起本地项目的时候,发现发送跨域请求时请求头携带不上cookie,经过网上冲浪了一下发现很多人开发时都会遇到这个问题,所以在这做一个记录
原因
chrome升级到80版本之后,cookie的SameSite属性默认值由None变为Lax(可能存在同一版本不同人的浏览器表现不同)
在Lax模式下 , 以下跨域方法会受影响:
所以我们在发跨域请求的时候,一直没能携带上cookie,原来是你!same-site属性!!!
SameSite 是什么鬼
既然找到原因了,就来看一下SameSite 究竟是个什么鬼,谷歌为啥要把它改来改去的呢
网站利用 cookie 记录用户的登录状态,但是cookie存在一个缺点就是他可以被第三方请求头给携带,这一点也是造成CSRF攻击的原因,为了从源头解决这个问题,谷歌从Chrome 51 开始,浏览器的 Cookie 新增加了一个SameSite属性,用来防止 CSRF 攻击和用户追踪。
SameSite 的三个值
分别是:
- Strict
- Lax
- None
Strict
Strict最为严格,完全禁止第三方 Cookie,跨站点时,任何情况下都不会发送 Cookie。换言之,只有当前网页的 URL 与请求目标一致,才会带上 Cookie。
Set-Cookie: CookieName=CookieValue; SameSite=Lax;
这个规则过于严格,可能造成非常不好的用户体验。比如,当前网页有一个 GitHub 链接,用户点击跳转就不会带有 GitHub 的 Cookie,跳转过去总是未登陆状态。
Lax
Lax规则稍稍放宽,大多数情况也是不发送第三方 Cookie,但是导航到目标网址的 Get 请求除外。
Set-Cookie: CookieName=CookieValue; SameSite=Lax;
设置了Strict或Lax以后,基本就杜绝了 CSRF 攻击。当然,前提是用户浏览器支持 SameSite 属性。
None
Chrome 计划将Lax变为默认设置。这时,网站可以选择显式关闭SameSite属性,将其设为None。不过,前提是必须同时设置Secure属性(Cookie 只能通过 HTTPS 协议发送),否则无效。 下面的设置无效。
Set-Cookie: widget_session=abc123; SameSite=None
下面的设置有效
Set-Cookie: widget_session=abc123; SameSite=None; Secure
解决方法
说了这么多,其实归根结底把SameSite的属性设置为None就可以解决跨域携带cookie的问题,解决的方式有这三种:
-
设置浏览器 谷歌浏览器里面: chrome://flags/ 把SameSite by default cookies这个参数设置成disabled
-
后端响应头设置: Set-Cookie: widget_session=abc123; SameSite=None; Secure
-
Nginx设置: 在 nginx 的 location 中配置: proxy_cookie_path / "/; httponly; secure; SameSite=None";