记SameSite属性导致的跨域携带Cookie丢失

Posted Faylinn

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了记SameSite属性导致的跨域携带Cookie丢失相关的知识,希望对你有一定的参考价值。

平台一直使用一套骚操作来完成了单点登录,主要利用跨域cookie来获取redis中缓存的用户信息来判断是否登录;突然有天失效了,于是有了此文;

平台背景:

  1. 现有A、B两个平台,A登录后,将用户登录信息放入redis并获取到key,将key存入http://A/user/的Cookie下;
  2. B平台登录的时候跨域调用http://A/user/auth/acquire请求,此请求会携带这个域下的Cookie
  3. 后台服务拿到Cookie中的key去reids查询到登录信息,返回登录成功;
  4. 完成整个的单点登录逻辑;

翻车现场:

  • 测试提出单点登录失效,在A平台登录成功后,访问B平台仍然需要登录;

于是开始排查:

  1. 查看A平台登录后,http://A/user/的Cookie下存在key, 此处没有问题;
  2. 访问B平台时,B平台调用http://A/user/auth/acquire接口,但是接口缺失Cookie;

。。。。

之前明明是好的!!!

排查

详细查看下请求

i讯飞图片_1624361309109.png

发现了一个感叹号,查看内容,发现了SameSite属性,且是因为SameSite=Lax导致无法set-cookie, 通过查询了解一下这个属性;可以看到阮大大的博客有介绍这个属性;

http://www.ruanyifeng.com/blog/2019/09/cookie-samesite.html

以下摘自博客:


Cookie 的SameSite属性用来限制第三方 Cookie,从而减少安全风险。

它可以设置三个值。

  • Strict
  • Lax
  • None

2.1 Strict

Strict最为严格,完全禁止第三方 Cookie,跨站点时,任何情况下都不会发送 Cookie。换言之,只有当前网页的 URL 与请求目标一致,才会带上 Cookie。

Set-Cookie: CookieName=CookieValue; SameSite=Strict;

这个规则过于严格,可能造成非常不好的用户体验。比如,当前网页有一个 GitHub 链接,用户点击跳转就不会带有 GitHub 的 Cookie,跳转过去总是未登陆状态。

2.2 Lax

Lax规则稍稍放宽,大多数情况也是不发送第三方 Cookie,但是导航到目标网址的 Get 请求除外。

Set-Cookie: CookieName=CookieValue; SameSite=Lax;

导航到目标网址的 GET 请求,只包括三种情况:链接,预加载请求,GET 表单。详见下表。

请求类型 示例 正常情况 Lax
链接 <a href="..."></a> 发送 Cookie 发送 Cookie
预加载 <link rel="prerender" href="..."/> 发送 Cookie 发送 Cookie
GET 表单 <form method="GET" action="..."> 发送 Cookie 发送 Cookie
POST 表单 <form method="POST" action="..."> 发送 Cookie 不发送
iframe <iframe src="..."></iframe> 发送 Cookie 不发送
AJAX $.get("...") 发送 Cookie 不发送
Image <img src="..."> 发送 Cookie 不发送

设置了StrictLax以后,基本就杜绝了 CSRF 攻击。当然,前提是用户浏览器支持 SameSite 属性。

2.3 None

Chrome 计划将Lax变为默认设置。这时,网站可以选择显式关闭SameSite属性,将其设为None。不过,前提是必须同时设置Secure属性(Cookie 只能通过 HTTPS 协议发送),否则无效。

下面的设置无效。

Set-Cookie: widget_session=abc123; SameSite=None

下面的设置有效。

Set-Cookie: widget_session=abc123; SameSite=None; Secure

很显然,Chrome是支持SameSite属性的,且通过资料可以知道在Chrome 80+版本,Chrome还将SameSite默认值改为了Lax,这也是导致此问题的主要原因;

以下是Chrome的特性介绍:

A cookie associated with a cross-site resource at accounts.google.com/ was set without the SameSite attribute. A future release of Chrome will only deliver cookies with cross-site requests if they are set with SameSite=None and Secure. You can review cookies in developer tools under Application>Storage>Cookies and see more details at https://www.chromestatus.com/feature/5088147346030592 and https://www.chromestatus.com/feature/5633521622188032

尝试解决:

在Chrome启动命令中,添加--disable-features=SameSiteByDefaultCookies命令,即可关闭SameSite属性,此时问题修复;

步骤如下:

  1. 找到Chrome目录,新建Chrome的快捷方式

  2. 右击快捷方式的属性,将属性命令复制到目标栏中

image20210622193746587.png image-20210622193746587

  1. 保存,关闭Chrome,然后通过新建的快捷方式打开Chrome;

i讯飞图片_1624362118749.png

发现已经可以携带Cookie啦!

最后:

很显然,我们不能要求客户来干这种事情。

所以结局是准备重新弄一下单点登录;

以上是关于记SameSite属性导致的跨域携带Cookie丢失的主要内容,如果未能解决你的问题,请参考以下文章

dajngo设置cookie的samesite属性

对于未来chrome80 samesite问题的兼容解决方案

<URL> 处的跨站点资源设置为没有 `SameSite` 属性 .NET

使用 SameSite 和 Secure 属性设置 Google Tag Manager cookie

解决携带身份信息的跨域请求

记一次uwsgi导致的跨域问题