Получить токен CSRF в тесте

Я пишу функциональный тест, и мне нужно сделать запрос ajax post. "Недопустимый токен CSRF. Повторите отправку формы. Как я могу получить токен в своем функциональном тесте?

$crawler = $this->client->request(
  'POST', 
  $url, 
  array(
      'element_add' => array(
          '_token' => '????',
          'name'   => 'bla',
      )

  ), 
  array(), 
  array('HTTP_X-Requested-With' => 'XMLHttpRequest')
);

Ответы

Ответ 1

Генератор токенов CSRF является обычным сервисом symfony 2. Вы можете получить услугу и создать токен самостоятельно. Например:

    $csrfToken = $client->getContainer()->get('form.csrf_provider')->generateCsrfToken('registration');
    $crawler = $client->request('POST', '/ajax/register', array(
        'fos_user_registration_form' => array(
            '_token' => $csrfToken,
            'username' => 'samplelogin',
            'email' => '[email protected]',
            'plainPassword' => array(
                'first' => 'somepass',
                'second' => 'somepass',
            ),
            'name' => 'sampleuser',
            'type' => 'DSWP',
        ),
    ));

ГенерацияCsrfToken получает одно важное намерение параметра, которое должно быть одинаковым в тесте, а в противном случае - сбой.

Ответ 2

После длительного поиска (я ничего не нашел в doc и в сети о том, как извлечь токен csrf), я нашел способ:

$extract = $this->crawler->filter('input[name="element_add[_token]"]')
  ->extract(array('value'));
$csrf_token = $extract[0];

Извлеките токен из ответа, прежде чем делать запрос.

Ответ 3

В symfony 3, в вашем WebTestCase, вам нужно получить токен CSRF:

$csrfToken = $client->getContainer()->get('security.csrf.token_manager')->getToken($csrfTokenId);

Чтобы получить $csrfTokenId, лучший способ - заставить его в параметрах вашего FormType():

class TaskType extends AbstractType
{
    // ...

    public function configureOptions(OptionsResolver $resolver)
    {
        $resolver->setDefaults(array(
            'csrf_token_id'   => 'task_item',
        ));
    }

    // ...
}

Итак, в этом случае: $csrfTokenId = "task_item";. Или вы можете попробовать использовать значение по умолчанию, которое будет именем вашей формы.

Затем используйте его как параметр post:

$client->request(
  'POST',
  '/url',
  [
    'formName' => [
      'field' => 'value',
      'field2' => 'value2',
      '_token' => $csrfToken
    ]
  ]
);