我希望能够手动提交包含我创建的数据的symfony表单,但似乎我在提交的数据中缺少CSRF令牌,因此验证失败。
表单很简单 - 只有一个字段(让我们说'名称'作为参数)作为没有约束的文本字段。
$data = [];
if ($someCondition) {
$data['name'] = 'steve';
}
$form = $this->createForm('FooType', $data);
if (!empty($data)) {
$form->submit($data);
} else {
$form->handleRequest($request);
}
if ($form->isSubmitted() && $form->isValid()) {
// do something
}
如果我设置$data['name']
表单提交但我得到The CSRF token is invalid. Please try to resubmit the form.
如何提交正确的令牌或覆盖此行为?
答案 0 :(得分:1)
我看到你将此标记为symfony2
个问题。考虑到这一点,您可以通过将其注入您的数据提供有效的CSRF令牌,思想,解决方案在<2.6
和>=2.6
版本中有所不同,据我所知。
2.6
版本:$provider = $this->get('form.csrf_provider');
$token = $provider->generateCsrfToken(''); // INTENTION = empty_string, by default
$data['<<YOUR_FORM_NAME']['_token'] = $token; // be sure to change the form name
2.6
+ 事情有点不同,因为表单现在使用TokenManagerInterface
组件提供的Security
:
$tokenId = ....;
$token= (string) $this->get('security.csrf.token_manager')->getToken($tokenId);
$tokenValue = $token->getValue();
现在,$tokenId
可以是很多东西,如Form的公开测试所述:
$tokenId = $options['csrf_token_id'] ?:
($form->getName() ?:
get_class($form->getConfig()->getType()->getInnerType()));
但是如果你研究一下,默认值为$form->getName()
,直到2.8
。我认为2.8
删除了getName()
方法的抽象,因此,2.8
以及之后将使用笨重的值:
get_class($form->getConfig()->getType()->getInnerType())
这一切都适用,除非您在表单类型中注入csrf_token_id
选项。
好的,所以看来我的错误推定是关于令牌密钥。虽然您确实获得了有效令牌,但未使用该令牌。在我的示例中,我有单独的FormType命名空间AppBundle\Form\SomeFooType
,并且使用的实际令牌ID为some_foo
。
我制作了一个工作示例的pastebin(版本2.8.8
,同样在3.1.2
按预期工作):http://pastebin.com/ks2jSeh7
希望这有点帮助。