我现在正在为我的cookie实现SameSite
。我已经有HttpOnly
和Secure
,所以我认为这可能没什么大碍。
好吧,事实证明,一旦实施该设置,很多东西就会坏掉。 SameSite=Lax
和SameSite=Strict
都发生了这种情况。我进行了一些研究,发现这是由于SSO容易因SameSite设置为Lax
或Strict
(而不是None
)而损坏:
我的主浏览器(Iron 70)基于Chromium 70,因此我从未遇到过2月份向Chrome 80用户推出的更改,该更改默认是将没有SameSite
值的Cookie设置为Lax
。我安装了最新的Google Chrome浏览器便携式设备以进行检查,有趣的是,该功能目前不是(很可惜)默认为SameSite=Lax
,因为它可能曾经使用过-我的网站才在那里中断了一旦我明确启用以下标头:
Header edit Set-Cookie ^(.*)$ $1;SameSite=Lax
这似乎是因为在没有显式SameSite
的情况下,Chromium默认将其视为"LAX + POST w/ 2-minute rule"(我正在快速测试,所以它在2分钟内)。
即使使用Lax
,我所有的单点登录都已中断,并且我的实时聊天不再起作用-使用Websockets或XHR请求。当我尝试进行单点登录时,我最终还是退出了主要网站,这也没有多大意义-基本上,一切都搞砸了。
是否有希望使XHR或Websockets与Lax
一起使用?我在chat.example.com
上聊天,但也可以在sub.someotherdomain.org
上的侧面板中访问它。我的猜测是,这里的答案是否,解决该问题的唯一方法是使URL在同一域中可用,而Apache只是在幕后指向同一脚本。烦人,但这可以完成-但是还有另一种方法吗?
我的更大问题是:单点登录与Lax
和Strict
本质上不兼容吗?我在这方面还没有发现太多。所有文章似乎都认为用Lax
来破坏SSO是不可避免的,甚至有一些图表解释了为什么会破坏,但是SSO是否必须那样?
大多数站点都说要SameSite=None
来解决此问题,并在所有用户代理中强制执行旧的行为。从技术上讲,这行得通,但我想知道是否有希望使用Lax
替代方法?如何在不屈服于SameSite=None
的情况下使其工作?
答案 0 :(得分:0)
TL; DR-是的,您可以使用
SameSite=Lax
(但不能使用SameSite=Strict
)并且不会破坏SSO!
关于SameSite
cookie,有两点要注意:
POST
GET
的跨域请求来源:https://www.wst.space/cookies-samesite-secure-httponly/
严格根本不起作用,因为它阻止了任何形式的跨源请求发送cookie,这使得SSO完全不可能。 Strict
甚至不是可行的候选人。
这给我们留下了Lax
和None
(到目前为止是默认值,并逐渐被Lax
取代)。
- 是否有希望让XHR或Websocket重新与
Lax
一起使用?我在chat.example.com
聊天,但我也允许访问 在sub.someotherdomain.org
上的侧面板中显示。我的猜测是 答案是否,解决该问题的唯一方法是 Apache仅指向同一域上可用的URL 相同的脚本在幕后。烦人,但可以完成-但是 还有另一种方法吗?
否。
这里最好的解决方案是在幕后重写URL,因此您无需维护重复的资源。使用Apache的mod_rewrite
重写URL或简单地执行include('path/to/file.php')
都是一个简单的解决方案。返回的 内容将完全相同-但如果它需要发送Lax
cookie,则浏览器必须将其发送到当前域的祖先域。
- 我更大的问题是:单点登录本质上与
Lax
和Strict
不兼容吗?
不,幸运的是,不!
我并没有发现太多 这个。所有文章似乎都将使用
Lax
来破坏SSO视为 不可避免,甚至有一些图解释了为什么 休息,但SSO是否必须那样?
是 是真的,很多SSO页面做以SameSite=Lax
中断-但这不是 不可避免-特定于实现。让我们比较一下原始方法和与SameSite=Lax
cookie兼容的修订方法。
SameSite=None
)sub.example.org
-当前未登录,因为此站点上未设置cookie example.com
上用于SSO的页面-如果未在此进行身份验证,它将重定向回并给出用户名/密码提示。如果用户已通过验证,请继续。example.com
上,读取用户的会话数据并为SSO调用创建唯一的令牌。将令牌转储到数据库中,并使用插入的令牌将其发布回原始站点。sub.example.org
,读取已发布的令牌并在数据库中查询该令牌,然后从中检索用户ID。sub.example.org
上的本地会话中设置用户ID-由于$_SESSION['mysession']
在example.com
和sub.example.org
上返回相同的信息,因此该会话可以按预期工作(因为用户ID永远不会更改,从技术上讲,它们是重复的Cookie)。 这将以SameSite=Lax
断开。为什么?因为发给身份验证者的原始请求使用的是POST
请求-这是对外部域的请求-SameSite=Lax
和 SameSite=Strict
都认为这很危险-并且跨域POST
不会将Cookie发送到目标。因此,Cookie不可用,并且验证者不知道要验证的用户,因此它不能为该用户创建临时令牌,然后再发回。这就是为什么这不起作用。
但是,这里要注意的重要一点是POST
请求 没有发送任何敏感数据 (至少在上述实现中) 。只是询问进行身份验证-它甚至没有任何敏感数据要发送!
那么,为什么我们首先POST
?回想一下SameSite=Lax
允许第一级GET
导航(SameSite=Strict
不允许)。因此,我们可以简单地使用GET
而不是POST
来进行初始重定向 。
如何在不屈服于
SameSite=None
?
这是怎么回事。由于Lax
允许使用最高级别的GET
,但不允许使用POST
(这可能是“危险的”),因此请使用GET进行初始重定向,而不要使用POST。
矛盾的是,GET
的安全性可能不及POST
,但是敏感数据(用户令牌)仅在最终重定向上发送回请求身份验证的站点-初始重定向仅表示“嘿,我正在请求验证”。
这里的a brief excerpt支持这种可能性,得出的结论是:
最后,IdP 应继续以在其Cookie起作用 浏览器默认将其设置为SameSite = Lax(当前在 Chrome 78-81和Firefox 72设置了相同的站点默认标志)。 通常,只有当JSESSIONID出现时,IdP本身才会中断 设置为SameSite'Strict'(严格),除了什么时候 明确尝试使用旧版Safari设置SameSite = None 在MacOS <= 10.14上以及在iOS <= 12上的所有WebKit浏览器上 (https://bugs.webkit.org/show_bug.cgi?id=198181)。但是关于 要实现单点登录,您可能会发现运行质量下降,并且 发生以下可能性:
初始重定向需要在授权域上使用cookie,而请求授权的域不是在请求cookie-它是根据POST
对其设置 cookie。因此,从理论上讲,这应该与Lax
一起使用,因为在最终的POST
请求(仅初始请求)上不需要cookie。最终的POST
重定向将无法根据该请求发送Cookie……但这不需要-我们将在{{1} }本身,并根据此设置cookie。天才!
原始SSO -需要POST
:
SameSite=None
到身份验证提供者POST
或未定义的None
)并创建临时令牌 修订后的SSO -与SameSite
兼容:
SameSite=Lax
到身份验证提供者GET
,而不是GET
)并创建临时令牌一个区别-就是这样-初始重定向上为POST
,而不是GET
。这是可行的,因为初始重定向不包含任何敏感信息。这个POST
很可能是POST
。通过将其设置为一个,我们可以提高整个会话cookie以及所有“记住我” cookie的安全级别-不错!
我已经在Chromium 70和Chrome 84中对此进行了测试,并带有严格的标志和阻止了第三方Cookie的功能(因此没有“ Lax + POST”,只是“ Lax”)。这确实有效。您还可以将任何“记住我” cookie设置为GET
-如果由于没有正在进行的会话,验证者需要使用它们自发地创建会话,则只要存在重定向,就可以使用这样做的cookie。 SameSite=Lax
而不是GET
-我们很好!
SSO 可以与POST
一起使用。显然,XHR,动态CSS,websocket等将不会,但是可以将它们简单地代入原始域之后。通过在初始重定向上使用Lax
而不是GET
,您可以转到使用POST
使用cookie。
更复杂的SSO流程可能有所不同-我在这里给出的只是一个非常简单的SSO示例。但是,SSO和SameSite=Lax
互不兼容-您可以通过稍微调整SSO设置使其工作,如果您需要进行其他更改,则不会中断。
请注意,您仍然仍可以与SameSite=Lax
进行会话-如果您的整个站点都在一个主机名上并且非常敏感,我建议您改为使用。但是,如果需要执行SSO,则至少可以使用SameSite=Strict
(当然不能使用SameSite=Lax
)。