【问题标题】:Symfony forms returning CSRF token is invalid from AJAX requests从 AJAX 请求返回 CSRF 令牌的 Symfony 表单无效
【发布时间】:2020-01-31 11:44:31
【问题描述】:

我们有一个 Symfony 4.3 应用程序,它有一个发出多个 AJAX 请求的页面。每个 AJAX 响应都包含几个表单,每个表单都有自己的 CSRF 令牌。但是,只有一个 AJAX 调用设法将其令牌存储在会话中。因此,AJAX 请求中的所有表单都将失败并显示消息

The CSRF token is invalid. Please try to resubmit the form.

除了一种能够在会话中正确保存其令牌的表单。

会话存储在redis中。

在进行多个 AJAX 调用时,如何确保所有 CSRF 令牌都存储在会话中?

【问题讨论】:

    标签: ajax session redis csrf symfony4


    【解决方案1】:

    CSRF 令牌部分使用 cookie。当您在一个页面上生成两个 CSRF 并提交其中一个表单时,您就是在使 cookie 无效。

    如果没有对框架本身进行一些扩展,我只能看到一种解决方法——而且相当迂回:

    您可以做的是设置一个控制器来生成您的应用程序表单。

    在初始页面加载时,您的控制器将加载登录表单以及应用程序表单。通过 AJAX 提交登录表单后,您还将仅向控制器请求应用程序表单(这也会给用户一个新的 cookie)。使用 javascript,您可以从新表单中提取新的 csrf 令牌并将其注入到原始应用程序表单中。然后,当您提交应用程序表单时,它应该有一个新的、有效的 csrf 令牌。

    举例说明:

    获取应用表单和登录表单 -> 通过 AJAX 提交登录 -> 在后台通过 AJAX 获取应用表单 -> 窃取新应用表单的 csrf 令牌并将其注入第一个应用表单 -> 提交应用表单。

          $.ajaxSetup({
      headers: {
        'X-CSRF-TOKEN': $('meta[name="csrf-token"]').attr('content')
      }
    });
    

    将此添加到您的标题中->>

    <meta name="csrf-token" content="{{ csrf_token() }}">
    

    【讨论】:

    • 我认为 cookie 只是存储 PHPSESSID。然后服务器使用 PHPSESSID 来检索存储在服务器上的实际会话。在我的情况下,会话存储在 REDIS 实例中。所以我不确定我是否理解你的解决方案。此外,需要明确的是,所有表单都有一个 CSRF 令牌。问题是服务器没有将其存储在用户会话中。
    猜你喜欢
    • 1970-01-01
    • 2021-01-01
    • 2019-11-20
    • 1970-01-01
    • 2014-08-17
    • 2020-05-19
    • 2020-07-27
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多