我创建了一个Symfony2的形式,并将其绑定到请求。 我需要明确地确保CSRF令牌是否与形式的其余部分之前有效/无效。
$form['_token']->isValid()
抛出OutOfBoundsException
“儿童_token不存在”具有消息
我还可以验证所呈现的表单包含_token
场。 在情况下CSRF值是无效的, $form->isValid()
返回false。
我缺少的是在这里吗?
更新1:
控制器(部分):
private function buildTestForm() {
$form = $this->createFormBuilder()
->add('name','text')
->getForm();
return $form;
}
/**
* @Route("/test/show_form", name="test.form.show")
* @Method("GET")
*/
public function showFormTest()
{
$form = $this->buildTestForm();
return $this->render('TestBundle::form_test.html.twig', array('form' => $form->createView()));
}
/**
* @Route("/test/submit_form", name="test.form.submit")
* @Method("POST")
*/
public function formTest()
{
$form = $this->buildTestForm();
$form->bind($this->getRequest());
if ($form['_token']->isValid()) {
return new Response('_token is valid');
} else {
return new Response('_token is invalid');
}
}
模板
{# Twig template #}
<form action="{{ path('test.form.submit') }}" method="post" {{ form_enctype(form) }}>
{{ form_widget(form) }}
<input type="submit" name="go" value="Test Form" />
</form>
有没有记录的方式来标记手动检查CSRF。 Symfony的自动验证该令牌的存在性和准确性。 http://symfony.com/doc/current/book/forms.html#csrf-protection
但是有一个CSRF提供商:
http://api.symfony.com/2.0/Symfony/Component/Form/Extension/Csrf/CsrfProvider/SessionCsrfProvider.html
和
http://api.symfony.com/master/Symfony/Component/Form/Extension/Csrf/CsrfProvider/DefaultCsrfProvider.html
商标类能够通过使用方法generateCsrfToken()提供CSRF保护您可以生成一个CSRF令牌。 这种方法你应该通过一个值,是唯一应该被固定以防止CSRF攻击的网页。 该值并不一定是秘密的。 此接口的实现负责增加更多的秘密信息。
如果你想确保对CSRF攻击表单提交,你可以提供一个“意向”的字符串。 这样,您确保表单只能绑定到设计用于处理表单使用相同字符串的意图验证CSRF令牌isCsrfTokenValid()的网页,也就是。
您可以检索这样的供应商
$csrf = $this->get('form.csrf_provider');
然后使用可使用
public Boolean isCsrfTokenValid(string $intention, string $token)
Validates a CSRF token.
参数字符串$意图用于生成所述令牌CSRF字符串时$令牌由浏览器所提供的令牌的意图
返回值Boolean是否由浏览器提供的令牌是正确的
你需要FINDE出你的形式使用意向的字符串。
在SO一些有趣的帖子:
Symfony的CSRF和Ajax
与CSRF令牌Symfony2的链接
除了artworkad,你可以指定一个意图:
枝条:
<form method="post">
<input type="text" name="form_name[field]" value="" />
<input type="hidden" name="_csrf_token" value="{{ csrf_token('form_name') }}">
</form>
PHP:
$token = $request->request->get('_csrf_token');
$csrf_token = new CsrfToken('form_name', $token);
var_dump($this->get('security.csrf.token_manager')->isTokenValid($csrf_token));
或不:
枝条:
<form method="post">
<input type="text" name="field" value="" />
<input type="hidden" name="_csrf_token" value="{{ csrf_token('') }}">
</form>
PHP:
$token = $request->request->get('_csrf_token');
$csrf_token = new CsrfToken('', $token);
var_dump($this->get('security.csrf.token_manager')->isTokenValid($csrf_token));
我不知道这一点,但你尝试过对未映射场验证:
$violations = $this->get('validator')->validatePropertyValue($entity, '_token', $form['_token']);
if (count($violations)) {
// the property value is not valid
}
另一种方式(如果你喜欢DI)来验证控制器的令牌之外(如在听众):
/** @var Symfony\Component\Security\Csrf\CsrfTokenManagerInterface */
private $csrfTokenManager;
public __construct(CsrfTokenManagerInterface $csrfTokenManager)
{
$this->csrfTokenManager = $csrfTokenManager;
}
public function isValid(): bool
{
return $this->csrfTokenManager->isTokenValid(
new CsrfToken('authenticate', $request->getRequest()->headers->get('X-CSRF-TOKEN'))
);
}