背景:最近有个A项目需要通过iframe嵌入另一个B网站的页面。在B网站登录的状态下,在A项目中打开B项目的链接一直获取不到登录状态。查了下之后发现是Chrome浏览器在80版本之后更新了cookie的安全策略。具体就是80版本之后,Chrome将SameSite的值有默认为None,改为了默认问Lax,这就导致cookie带不过去了。
SameSite介绍
Cookie 的SameSite属性用来限制第三方 Cookie,从而减少安全风险。
它可以设置三个值。
- Strict
- Lax
- None
Strict最为严格,完全禁止第三方 Cookie,跨站点时,任何情况下都不会发送 Cookie。换言之,只有当前网页的 URL 与请求目标一致,才会带上 Cookie
Lax规则稍稍放宽,大多数情况也是不发送第三方 Cookie,但是导航到目标网址的 Get 请求除外。
Chrome 计划将Lax变为默认设置。这时,网站可以选择显式关闭SameSite属性,将其设为None。不过,前提是必须同时设置Secure
性(Cookie 只能通过 HTTPS 协议发送),否则无效。
解决问题
知道问题之后,我们就开始解决问题。既然这个问题是因为SameSite的属性设置问题,那我们只需要把SameSite的属性由默认的Lax改为None即可。
方法0
用80版本之前Chrome浏览器不会存在这个问题,因为80版本之前的默认值是None。当然这种方式也不太可行,毕竟不能保证用户都用指定版本,而且Chrome还默认自动更新~
不过这也算是一种解决方案。
此处给出Chrome各版本的下载地址:https://www.slimjet.com/chrome/google-chrome-old-version.php
方法1(91版本之后不适用)
Chrome91版本之前可以通过浏览器设置来变更:
1.在chrome中打开链接: chrome://flags/
搜索samesite
2.将搜出来三个选项禁用(设为disable)后重启chrome,问题解决。
但是这种方法不太灵活,也不可能让用户去手动设置。而且从91版本之后,这个方式也被取消了,samesite并不会被显示出来了。
方法2
通过nginx或者Apache的配置来修改cookie,这里给出nginx的修改示例:
location / {
# your usual config ...
# hack, set all cookies to secure, httponly and samesite (strict or lax)
proxy_cookie_path / "/; secure; HttpOnly; SameSite=strict";
}
方法3
通过PHP代码层面来修改。
PHP写cookie有多种形式,常见有header()方法和setcookie()方法。
header('Set-Cookie: path=/; domain=.xxx.com; SameSite=None; Secure');
setcookie('key', 'value', 0, '/; SameSite=None; Secure');
这两个方法分别有需要注意的点:
-
header()方法注意第二个参数默认是true,会替换掉之前写入的cookie,就是说header()方法默认只会保留最后一次写入的cookie,如果想要都保留,需要将hader()方法的第二个参数设置为false。
-
stcookie()方法注意第4个参数$path的值不是
/
而是/; SameSite=None; Secure
这里需要重点强调的是:在百度和google中搜索出来的大部分结果,都只是告诉你怎么使写入的cookie的SameSite值为None。(上面的两个方法只能保证,通过此方法写入的当前的cookie的SameSite属性值被设置为了None)
但是,我们再解决问题时,需要考虑的是,已经运行很久的项目,本身会有自身写入cookie的逻辑,我们需要把那些cookie的SameSite值也要设置为None。
在我遇到的项目中,是使用stcookie()方法写入cookie,并且配置了COOKIE_PATH的常量,而我们如果要解决这个项目里其他cookie写入的SameSite属性值问题,就需要将原来path的值由/
改为/; SameSite=None; Secure
最终,我们可以看到请求地址中的所有cookie的SameSite属性都被设置为了None。