Functional testing form with CSRF enabled in Symfony
What is the best way of creating functional tests to test forms with CSRF protection enabled in Symfony?
Currently I have to add the following code before each form submittion:
$form = new sfGuardFormSignin();
$token = $form->getCSRFToken();
$token_name = $form->getCSRFFieldName();
Then I add the $token and $toke开发者_StackOverflown_name to form parameters like this:
call('/login', 'POST', array (
'signin' =>
array (
'username' => $username,
'password' => $password,
$token_name => $token,
)))
The option suggested in the documentation:
'_with_csrf' => true,
Doesn't work at all.
Is there more simple way to avoid adding token to each form tested manually? Or is there a way to turn off csrf checking when running tests?
The way I've described above is ok when you have to test 1-2 forms but if project contains tens unique forms it becomes a pain.
Of course, you can't use _with_csrf option if you call directly the url. You must pass from the form page, clicking on the submit button. Like so:
click('signin', array('signin' => array('username' => $username, 'password' => $password), array('_with_csrf' => true)))
The string 'signin' must be adapted to your form. You can also use a more label-independent string, like 'form#myform input[type="submit"]' instead of 'signin', adapting the id of your form.
As already suggested, you can disapble CSRF for login, it's really useful for forms that modifies data.
I personally don't use functional tests that extensively (probably to my own detriment), but you could always switch the CSRF protection off in your form class for testing purposes.
public function configure ()
$this->disableLocalCSRFProtection();
You can disable csrf protection for all forms just by adding additional compiler pass:
class CsrfProtectionCompilerPass implements CompilerPassInterface
{
/**
* {@inheritdoc}
*/
public function process(ContainerBuilder $container)
{
$env = $container->getParameter('kernel.environment');
if ($env == 'test') {
$container->setParameter('form.type_extension.csrf.enabled', false);
}
}
}
Or You can disable form extension completely by adding to config:
framework:
csrf_protection: false
btw, last solutions works only if You don't have explicitly set form option csrf_protection
I would turn off CSRF for testing environment.
You should get a CSRF token by showing the page including the form.
$browser->get('/login');
$dom = new DOMDocument('1.0', $browser->getResponse()->getCharset());
$dom->loadHTML($browser->getResponse()->getContent());
$domCssSelector = new sfDomCssSelector($dom);
$token = $domCssSelector->matchSingle('input[name="_csrf_token"]')->getNode()->getAttribute('value');
精彩评论