Exists some way in Symfony 2 to generate CSRF token at each rendering of form? In my controller I tried something like this:
$request = $this->get('request');
if ($request->getMethod() != 'POST') {
$csrf = $this->get('form.csrf_provider');
$date= new \DateTime("now");
$this->date = $date->format('Y-m-d H:i:s');
$token = $csrf->generateCsrfToken($this->date);
} elseif($request->getMethod() == "POST") {
$csrf = $this->get('form.csrf_provider');
$token = $csrf->generateCsrfToken($this->date);
}
$form = $this->createFormBuilder()
....
->add('_token','hidden',array(
'data' => $token
))->getForm();
if ($request->getMethod() == 'POST') {
$form->bindRequest($request);
if ($form->isValid()) {
DO something
}
}
All the time is in my request right token hash. But after bindRequest its change to default hash generated from security string in parameters.ini and isValid method returns certainly FALSE response. Exists some way, how to adjust it?
EDIT In response to theunraveler answer, I edited my controller and create my CSRF provider, but still im geting "The CSRF token is invalid. Please try to resubmit the form" error. My CSRF provider looks like this:
namespace My\Namespace;
use Symfony\Component\HttpFoundation\Session;
use Symfony\Component\Form\Extension\Csrf\CsrfProvider\CsrfProviderInterface;
class MyCsrfProvider implements CsrfProviderInterface
{
protected $session;
protected $secret;
protected $datetime;
public function __construct(Session $session, $secret)
{
$this->secret = $secret;
$this->datetime = new \DateTime('now');
$this->session = $session;
}
public function generateCsrfToken($intention)
{
return sha1($this->secret.$intention.$this->datetime->format('YmdHis').$this->getSessionId());
}
public function isCsrfTokenValid($intention, $token)
{
return $token === $this->generateCsrfToken($intention);
}
protected function getSessionId()
{
return $this->session->getId();
}
}
Than I add to config.yml service class:
services:
form.csrf_provider:
class: My\Namespace\MyCsrfProvider
arguments: [ @session, %kernel.secret% ]
And Controller I change To this:
//any form without _token field
$form = $this->createFormBuilder()
->add('field1')
->add('field2')->getForm()
if ($this->getRequest()->getMethod() == 'POST') {
$request = $this->getRequest();
$form->bindRequest($request);
if ($form->isValid()) {
Do something
return $this->redirect($this->generateUrl('somewhere'));
}
}
Cant be problem in seconds in my hash? Becouse if I remove seconds from datetime format, it works, but with 1 min expiration and its not a good solution. I think, the reason is, that the time was changed.