8

Firstly I'm a complete noobie with Symfony 2. The question sounds simple, if I try and put some context into why and how I need this it will start to get confusing.

In essence I've created a form, which I manually process, validate and insert using Doctrine etc. I am manually creating the form within a controller action (it's built dynamically from retrieved values from another object). I'm assuming there maybe better ways to do this, but as I'm new to Symfony and days of trawling the net, I can't see any solutions to what I need to do.

Therefore I'm not simply building a form against a class/entity etc and so I will manually need to add a CSRF token or some kind of protection.

In normal circumstances you would create the FormType and configure default options to have csrf_protection. Then a simple case of:

{{ form_widget(form._token) }}

and the csrf token is there.

As I'm dynamically building the form I am not sure how I can manually create a csrf token for my form. Has anyone had any experience of creating forms without a class and adding csrf protection?

Kind regards Paul Pounder

Alain Tiemblo
  • 36,099
  • 17
  • 121
  • 153
Paul Pounder
  • 244
  • 1
  • 5
  • 14

3 Answers3

26

I think what you are looking for is the following :

This will render a CSRF token. Use this function if you want CSRF protection without creating a form

{{ csrf_token("intention") }}

For example:

<a href="{{ path('remove_stuff', {token: csrf_token('intention')}) }}">Remove</a>

source

To validate this token from a controller, you can do:

if ($this->get('token') !== $this->get('security.csrf.token_manager')->getToken('intention')->getValue()) {
    throw new \Symfony\Component\Security\Core\Exception\InvalidCsrfTokenException('Invalid CSRF token');
}

To simplify check the token on Symfony 2.6 or newer

if ($this->isCsrfTokenValid('intention', $submittedToken)) {
    // ... do something, like deleting an object
}  
Omar Ghorbel
  • 680
  • 5
  • 12
Żabojad
  • 2,946
  • 2
  • 32
  • 39
  • What is the argument of the csrf_token? the name of the form? – fain182 Dec 27 '13 at 11:48
  • @fain182 this is a kind of filter for your csrf token so that only controllers/pages which know this id will validate your csrf token. More info there: http://api.symfony.com/2.3/Symfony/Component/Form/Extension/Csrf/CsrfProvider/CsrfProviderInterface.html – Żabojad Jan 11 '14 at 10:38
12

Connection between Form Type and token:

{{ csrf_token("task_item_intention") }}

and in Form Type:

class TaskType extends AbstractType
{
// ...

public function setDefaultOptions(OptionsResolverInterface $resolver)
{
    $resolver->setDefaults(array(
        'data_class'      => 'Acme\TaskBundle\Entity\Task',
        'csrf_protection' => true,
        'csrf_field_name' => '_token',
        // a unique key to help generate the secret token
        'intention'       => 'task_item_intention',
    ));
}

// ...
}
d3uter
  • 737
  • 9
  • 14
  • 1
    For Symfony2.7+ use `csrf_token_id` instead of `intention` in defaults options. Check out link below for more information. You can also skip `csrf_protection` and `csrf_field_name`, as they are by default configured in the same maner as you can see above. http://symfony.com/doc/current/form/csrf_protection.html – broiniac Dec 20 '17 at 19:28
6

In (my) normal circumstances you create a form and do not specifically configure CSRF - it happens automatically, and you use form_rest(form) or form_end(form) to render the hidden input with CSRF token. I do not believe that this is any different for a form not backed by a model.

dylan oliver
  • 1,274
  • 9
  • 16