Как проверить, не установлен ли установленный токен CSRF в Symfony2?

Я создал форму Symfony2 и связал ее с запросом. Мне нужно явно убедиться, что токен CSRF действителен/недействителен, прежде чем продолжить остаток формы.

$form['_token']->isValid() throws 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');
    }
}

Шаблон

{# 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>

Ответ 1

Нет документального способа проверки маркера 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. Вы можете создать CSRF токена, используя метод generateCsrfToken(). К этому методу вы должен передать значение, которое уникально для страницы, которая должна быть защищена против атак CSRF. Это значение необязательно должно быть секрет. Реализации этого интерфейса отвечают за добавление более секретную информацию.

Если вы хотите обеспечить отправку формы против атак CSRF, вы может предоставить строку "намерение". Таким образом, убедитесь, что форма может быть привязана только к страницам, которые предназначены для обработки формы, то есть использовать одну и ту же строку намерения для проверки токена CSRF с isCsrfTokenValid().

Вы можете получить поставщика, как это

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

может использовать

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

Validates a CSRF token.

Параметры string $intent Цель, используемая при создании Символьная токена CSRF $token Токен, предоставляемый браузером

Возвращаемое значение Boolean Является ли токен, предоставленный браузером, правильно

Вам нужно найти строку намерения, используемую вашей формой.

Некоторые интересные сообщения на SO:

Symfony CSRF и Ajax

Ссылки Symfony2 с токеном CSRF

Ответ 2

В дополнение к artworkad вы можете указать намерение:

Twig:

<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));

Или не:

Twig:

<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));

Ответ 3

Я не уверен в этом, но вы попробовали валидатор в неотображенном поле:

$violations = $this->get('validator')->validatePropertyValue($entity, '_token', $form['_token']);
if (count($violations)) {
    // the property value is not valid
}