17

好的,我用谷歌搜索了这个,但我发现的所有内容都是在常规 Symfony 表单处理的上下文中谈论 Symfony 表单(例如 form_widget()、创建 FormType 类等)。我的 Symfony 项目中有很多这样的表格,它们工作得很好。

但:

我还有一些非常复杂的 AJAX 表单,我想手动构建(使用普通的旧 HTML 和 JS)。我仍然想利用 Symfony 的表单验证功能和 CSRF 保护。但是,由于某种原因,在将 isValid() 用于手动创建的表单时,我无法使 CSRF 工作。

这是我想要完成的一个例子:

在我的视图控制器中,我设置了 _token:

$_token = $this->get('form.csrf_provider')->generateCsrfToken('form');

在我看来(手动创建的表单)(从我的视图控制器获取 _token):

<html>
  <form method="post">
    <input type="hidden" name="form[_token]" value="{{ _token }}">
    <input type="hidden" name="form[id]" value="1">
    <input type="submit" value="Submit">
  </form>
</html>

在我的动作控制器中(提交表单时,我正在尝试执行以下操作):

//Create form (for validation purposes)
$form = $this->get('form.factory')
  ->createBuilder('form', array('id' => $request->get('id')))
  ->add('id', 'hidden')
  ->getForm();

//Bind form
$form->bind($request)

//Validate form
if($form->isValid()) {
  //... save data
}

//Return response...

出于某种原因,我无法让 isValid() 工作,我怀疑我的 _token 是没有正确使用的东西,但我不知道为什么。有没有人真正让手动表单与 Symfony 组件一起工作?有人对如何使这项工作有任何建议吗?

基本上,我想要完成的是:

  1. 手动创建 HTML 表单(具有 CSFR 保护且没有TWIG 表单小部件功能)

  2. 使用 Symfony 的表单功能来验证该表单

谢谢你。

4

4 回答 4

8

我认为你在这里的意图不匹配(参数传递给你的 CSRF 提供者)。我尝试按照您在上面写的那样生成表单并断点生成令牌。值为unknown

因此,请尝试传递unknown而不是传递form给您的generateCsrfToken电话,希望它应该可以工作。;)

编辑:

我刚刚完成了一些挖掘,现在它确实很有意义。

看课FormTypeCsrfExtension。显然,它是用于 CSRF 令牌保护的默认扩展。在线#80(可能不完全是您的情况)有一种方法setDefaultOptions通常在您的表单类型中被覆盖。无论如何,有一个名为的默认选项intention,其值为unknown==> 我们在这里看到的那个。

我的猜测是,您可以通过传递intention和设置您自己的值轻松地在您自己的表单类型中覆盖此选项(就像您csrf_protection在想要完全禁用 CSRF 保护时传递 => false 一样)。

于 2013-04-27T08:39:48.003 回答
5

注意:意图不再默认为未知。当我在 symfony 2.3 中检查它时,它似乎默认为类型名称:

$options['intention'] ?: ($builder->getName() ?: get_class($builder->getType()->getInnerType()))

如果有一些程序化的方式来获得使用的意图而不是依赖这些默认值,那就太好了。

于 2014-06-17T19:36:17.780 回答
4

我已经看到这已经解决了,但我也遇到了一些形式问题,并在这里看到了另一篇帖子:

symfony2 CSRF 无效

在我看来,他们的解决方案比制作我自己的令牌更好:

使用 {{ form_widget(form) }} 构建您的自定义表单没有问题。您所要做的就是像这样添加 _token:{{ form_widget(form._token) }}

于 2013-11-11T20:51:01.797 回答
0

我使用 Symfony 2.8 的解决方案:

在动作控制器中(提交表单时):

    $theToken = $request->get('Token');

    //Token Verification   
    $isValidToken = $this->isCsrfTokenValid('your_intention', $theToken);
    if ($isValidToken === false)
    {
        // Error
    }

检查我找到信息的页面:http: //api.symfony.com/2.8/Symfony/Component/Form/Extension/Csrf/CsrfProvider/CsrfProviderInterface.html#method_isCsrfTokenValid

于 2016-08-12T13:13:58.970 回答