如何在Symfony2中检查提供的CSRF令牌是否无效?

Vil*_*ila 11 validation csrf symfony-forms symfony

我创建了一个Symfony2表单并将其绑定到Request.在继续表单的其余部分之前,我需要明确确保CSRF令牌是否有效/无效.

$form['_token']->isValid()抛出OutOfBoundsException消息"Child _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');
    }
}
Run Code Online (Sandbox Code Playgroud)

模板

{# 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>
Run Code Online (Sandbox Code Playgroud)

Upv*_*ote 11

没有记录的方法来手动检查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

标记能够提供CSRF保护的类您可以使用generateCsrfToken()方法生成CSRF令牌.对于此方法,您应传递应针对CSRF攻击保护的页面唯一的值.该值不一定是秘密的.此接口的实现负责添加更多秘密信息.

如果您想确保针对CSRF攻击的表单提交,您可以提供"意图"字符串.这样,您可以确保表单只能绑定到设计用于处理表单的页面,即使用相同的意图字符串来使用isCsrfTokenValid()验证CSRF令牌.

您可以像这样检索提供者

$csrf = $this->get('form.csrf_provider');
Run Code Online (Sandbox Code Playgroud)

使用然后可以使用

public Boolean isCsrfTokenValid(string $intention, string $token)

Validates a CSRF token.
Run Code Online (Sandbox Code Playgroud)

参数string $ intent生成CSRF标记字符串时使用的意图$ token浏览器提供的标记

返回值Boolean浏览器提供的令牌是否正确

您需要找出表单使用的意图字符串.

有关SO的一些有趣帖子:

Symfony CSRF和Ajax

Symfony2与CSRF令牌链接

  • 从Symfony 2.4开始不推荐使用````security.csrf.token_manager```.http://api.symfony.com/2.7/Symfony/Component/Security/Csrf/CsrfTokenManagerInterface.html (3认同)

小智 11

除了artworkad,您还可以指定一个意图:

枝条:

<form method="post">
    <input type="text" name="form_name[field]" value="" />
    <input type="hidden" name="_csrf_token" value="{{ csrf_token('form_name') }}">
</form>
Run Code Online (Sandbox Code Playgroud)

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));
Run Code Online (Sandbox Code Playgroud)

或不:

枝条:

<form method="post">
    <input type="text" name="field" value="" />
    <input type="hidden" name="_csrf_token" value="{{ csrf_token('') }}">
</form>
Run Code Online (Sandbox Code Playgroud)

PHP:

$token = $request->request->get('_csrf_token');
$csrf_token = new CsrfToken('', $token);
var_dump($this->get('security.csrf.token_manager')->isTokenValid($csrf_token));
Run Code Online (Sandbox Code Playgroud)