如何为 Symfony3 上的 AJAX 调用添加 CSRF 保护?

Posted

技术标签:

【中文标题】如何为 Symfony3 上的 AJAX 调用添加 CSRF 保护?【英文标题】:How to add CSRF protection to AJAX call on Symfony3? 【发布时间】:2017-12-21 02:29:49 【问题描述】:

我正在开发一个网站,您可以在其中“添加朋友”另一个用户,就像 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') 【参考方案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,因为我有一个对象列表,所以我想为每个对象设置不同的令牌......这只是为了提高安全性。

以上是关于如何为 Symfony3 上的 AJAX 调用添加 CSRF 保护?的主要内容,如果未能解决你的问题,请参考以下文章

如何为使用 AJAX 获取的页面或内容添加书签?

如何为未经授权的 AJAX 调用而不是登录页面返回 JSON 响应作为 AJAX 响应?

如何为自托管 WCF 服务启用跨域调用

如何为 Rails 控制器添加延迟以进行测试?

如何为 UIToolbar 上的按钮添加滚动?

如何为Amazon AWS部署设置composer标志--no-dev