退出并重新登录后Laravel中出现419错误(多个选项卡)



我在Laravel应用程序中打开了两个选项卡。

我点击";注销";在一个选项卡中;注销";在第二个选项卡中。第二个logout曾经给出419错误,但我将其添加到了VerifyCsrfToken中间件中的排除列表中。我不明白为什么我需要CSRF保护才能注销。

但是,现在我有一个不同的问题。

在两个选项卡中注销后,两个选项卡都位于登录页面上。现在,如果我试图从第一个选项卡重新登录,我会收到419错误。从第二个选项卡,登录操作正常。

我该如何处理?我不想在用户点击"时向他们显示错误;"登录";,这是糟糕的用户体验。我也不想将登录路由排除在CSRF保护之外。

注意事项

在这个答案中,我将您的浏览器打开的选项卡命名为选项卡A标签B

只需考虑以下规则:

  • 您的浏览器一次为域激活一个会话(使用session_idcookie访问(
  • 客户端:每个打开的选项卡都可以有一个CSRF令牌,其形式、标题
  • 服务器端:会话变量中只有一个csrf令牌
  • 对于每个post请求,客户端和服务器令牌应该匹配,否则会出现419错误

注销时CSRF保护的必要性

没有必要在注销路由中阻止CSRF保护,因为它不是资源更改路径。CSRF Protection的CCD_ 3是件好事。

正在发生的场景

1

首先,您打开了选项卡AB,它们已登录并共享相同的会话和令牌

选项卡A-会话1-令牌x选项卡B-会话1-令牌x

2

单击选项卡A注销。它将从服务器清除会话。重定向回登录页面。在登录页面中,客户端请求服务器,为他创建了一个新的会话令牌

选项卡A-会话2-令牌y选项卡B-会话2(带有session_id的cookie用于域(-令牌x(客户端:显示在选项卡中/从服务器中删除,因为它在会话1中(

由于服务器端没有会话1,该会话持有令牌x因此选项卡B令牌与服务器y令牌不匹配

3

在选项卡B上发送注销。

如果您在启用csrf的情况下发送登出。中间件向您发送419,因为客户端上的令牌x和服务器上的令牌b之间存在错误。

如果其免于csrf,则**清除服务器端的会话**并将客户端重定向到登录页面,然后重定向服务器使用选项卡B的新csrf令牌创建新的会话

我假设您在注销路由上免除csrf保护,然后继续第二种情况。

选项卡A-会话3-令牌y选项卡B-会话3-令牌z

如您所见,服务器具有会话3,令牌为z。因此选项卡一个匹配错误

结论

正如你所看到的,这种不匹配有一些原因:

  • 会话(cookie(是浏览器范围,但令牌是选项卡范围
  • 用户在一个选项卡上做了一些事情,使其他选项卡有一个错误处理其表单令牌的会话

所以正如你所看到的,预防解决方案已经出现:

如果用户想要:

  • 打开多个选项卡
  • 在一个选项卡上注销(重新创建会话(
  • 继续使用其他打开的选项卡/表单(刷新可以解决问题(

解决方案

您必须使会话和令牌范围同步

有两种解决方案:

  1. 使令牌浏览器范围:使用XSRF而不是CSRF,这可以通过使用SPA客户端框架来实现。(优选(

  2. 使会话页面范围:

    • 将注销功能更改为不清除会话,只清除响应session_id

    • 使用隐藏输入(其本身向下(进行会话跟踪(obsolote(

我建议使用客户端的单页应用程序框架

避免"419页过期":

  1. 转到中间件
  2. VerifyCsrfToken.php
  3. 创建新方法句柄
use Closure;
use IlluminateSupportFacadesAuth;
public function handle($request, Closure $next)
{
if($request->route()->named('logout')) {
if (!Auth::check() || Auth::guard()->viaRemember()) {
$this->except[] = route('logout');
}   
}
return parent::handle($request, $next);
}

相关内容

  • 没有找到相关文章

最新更新