【问题标题】:Generate new CSRF token without reloading the entire form无需重新加载整个表单即可生成新的 CSRF 令牌
【发布时间】:2012-07-13 02:07:57
【问题描述】:

如果用户在使用我的 Symfony2 应用程序时在后台退出(由于会话到期或其他原因),我已经实现了一个 JS 层出现在屏幕上,允许用户立即重新登录并继续使用网站。

问题是,如果用户在填写表格的过程中退出了,在使用 JS 层重新登录后,他仍然在查看具有他已经设法输入的值的相同表格,但是他的会话变化。因此表单中的 CSRF 令牌无效。

有没有办法根据当前会话和特定表单生成新的 CSRF 令牌,通过 AJAX 抓取它并在表单中替换?或者也许有其他解决方案?

我不想禁用 CSRF 保护。

【问题讨论】:

  • 我没有足够的声誉来评论解决方案,所以我会这样做。 thecatontheflat 的答案可能会奏效,但在我看来,这会打破 CSRF 保护的整个概念:机器人可以简单地调用 AJAX 控制器,获取令牌并使用它与表单一起发布。

标签: symfony


【解决方案1】:

假设您使用默认的 CSRF Provider,在您的 AJAX 控制器中,您可以获取您的 CSRF Provider 服务并“要求”它重新生成令牌:

Symfony 2.3(及之前版本)

/** @var \Symfony\Component\Form\Extension\Csrf\CsrfProvider\SessionCsrfProvider $csrf */
$csrf = $this->get('form.csrf_provider');
$token = $csrf->generateCsrfToken($intention); 

return new Response($token);

Symfony 2.4

/** @var \Symfony\Component\Security\Csrf\CsrfTokenManagerInterface $csrf */
$csrf = $this->get('security.csrf.token_manager');
$token = $csrf->refreshToken($intention);

return new Response($token);

【讨论】:

  • 最佳解决方案!或者您可以在 Javascript 中生成令牌(它基本上是一个 sha1 哈希,或者您可以覆盖默认的 CsrfProvider 以拥有自己的令牌算法。);-)
  • 谢谢 :) 如果@grzechoo 可以同意并接受答案,那就太好了
  • 抱歉耽搁了,我离开了一段时间。公认! :)
  • 请注意,从 Symfony2.4 开始,form.csrf_provider 已过时
【解决方案2】:

使用它来重新生成 CSRF 令牌(自 Symfony2.4 起):

$csrf = $this->get('security.csrf.token_manager'); //Symfony\Component\Security\Csrf\CsrfTokenManagerInterface
$token = $csrf->refreshToken($intention); // Intention is specified in form type

return new Response($token);

【讨论】:

    【解决方案3】:

    是的,机器人可以获取 csrf 令牌并将某些内容发布到表单,但由于令牌绑定到会话,所以没关系。 CSRF 令牌并非旨在阻止机器人提交表单。

    【讨论】:

      【解决方案4】:

      对我来说,更简单的解决方案是在同一个表单上重定向用户,传递已经通过 POST 插入的数据。
      这样,令牌将以自动方式再次生成。
      此外,您不会丢失数据输入。

      【讨论】:

      • 谢谢,但我正在寻找更通用的解决方案。我目前有很多自定义验证功能,我必须一一检查我的所有表单并进行调整。一点也不轻松。
      猜你喜欢
      • 2012-09-18
      • 1970-01-01
      • 2018-07-29
      • 2014-10-16
      • 2011-12-21
      • 2021-01-22
      • 2014-06-20
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多