【问题标题】:How to add CSRF protection to AJAX call on Symfony3?如何为 Symfony3 上的 AJAX 调用添加 CSRF 保护?
【发布时间】:2025-12-08 02:25:01
【问题描述】:

我正在开发一个网站,您可以在其中“添加朋友”另一个用户,就像 facebook 一样。现在,我放了一个链接,当你点击它时,AJAX 调用就完成了。

在坚持新友谊之前,我检查请求是否是 Ajax,但我想更进一步并增加更多安全性。一个页面可以有超过 10 个链接(可能的请求),所以...我不知道我是只需要一个令牌,还是每个链接一个令牌。

另一个疑问是......如何使用 Symfony 生成令牌并检查是否有效?重点介绍如何在初始控制器上生成令牌,然后,如何在 addFriend 控制器(接收 ajax 调用)上进行验证。

我尝试使用它来生成令牌:

http://api.symfony.com/3.1/Symfony/Component/Security/Csrf/TokenGenerator/TokenGeneratorInterface.html

然后检查令牌:

https://symfony.com/doc/current/controller/csrf_token_validation.html

但始终返回令牌无效有效。

【问题讨论】:

  • 将表单创建为普通的 Symfony 表单,然后将其加载到您的模板中并通过 ajax 发送表单。它将像任何其他 Symfony 表单一样拥有 CSRF 令牌
  • 谢谢,但对我来说,为没有表单元素创建表单似乎是一种不好的做法。
  • 它将有一个元素 - CSRF 令牌。它可能会有其他隐藏字段。这不是坏习惯,它以预期的方式使用 Symfony 框架
  • 只需确保使用用于验证它的相同'token_id' 生成令牌。
  • 如果你在树枝上下文中,你可以使用{{ csrf_token('token_id') }}

标签: php jquery ajax symfony csrf


【解决方案1】:

我终于找到了解决问题的方法。

正如@yceruto 评论的那样,可以在没有任何形式的情况下生成csrf token,请参见:http://symfony.com/doc/current/reference/twig_reference.html#csrf-token

有了这个,我可以通过以下方式在 TWIG 上创建我的链接:

<a data-id="{{ user.id }}" class="card-link clickable sendFriendRequest" data-token="{{ csrf_token(user.id) }}">ADD_FRIEND</a>

然后,我像这样进行 AJAX 调用:

$('.elementsList').on('click','.sendFriendRequest', function () {

var userId = $(this).data('id');
var token = $(this).data('token');

$.post('/users/sendFriendRequest/'+userId, {token: token}
).done(function (response) {
    //Some code here

}).fail(function (response) {


});

});

最后,您使用以下代码检查令牌在您的控制器上是否有效:

$token = $request->request->get('token');

$isValidToken = $this->isCsrfTokenValid($townId, $token);

谢谢!

【讨论】:

  • $townId 是什么?那不是用来生成令牌的用户 ID 吗?
  • @Chris 我不知道他为什么要加$townId,你只要把token的标识符加为函数的第一个参数就行了。因此,如果您像这样csrf_token('foobar') 创建您的令牌,那么您可以像这样检查它的有效性:$this-&gt;isCsrfTokenValid('foobar', $token)
  • 对不起@Chris,我添加了对象ID,因为我有一个对象列表,所以我想为每个对象设置不同的令牌......这只是为了提高安全性。