2013-02-23 10 views
11

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

$form['_token']->isValid() throws OutOfBoundsException с сообщением «Ребенок _token не существует».

Я все еще могу проверить, что оказанная форма содержит поле _token. Если значение CSRF недействительно, $form->isValid() возвращает false.

Что мне здесь не хватает?


Update 1:

Controller (частичный):

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> 
+0

у вас отсутствует хотя бы код формы. – mpm

+0

@mpm, true - теперь добавлен полный код для воспроизведения проблемы. –

+0

Проверка подлинности CSRF выполняется автоматически http://symfony.com/doc/current/book/forms.html#csrf-protection –

ответ

10

Там нет документированного способа проверить 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

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

Symfony2 links with CSRF token

+3

Устаревший с Symfony 2.4, вместо этого используйте '' 'security.csrf.token_manager'''. http://api.symfony.com/2.7/Symfony/Component/Security/Csrf/CsrfTokenManagerInterface.html –

0

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

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

В дополнение к 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)); 
+0

Должен ли ajax-запрос регенерировать токен? – danidacar

+0

ajax - это то же самое!! – user3746259

+0

Вы можете регенерировать токен в ajax и обновить свое входное значение: 'public function tokenAction ($ intent) {$ csrf = $ this-> get ('security.csrf.token_manager'); $ token = $ csrf-> refreshToken ($ intent); return new Response ($ token); } ' –

Смежные вопросы