重定向后重新提交受csrf保护的表单(Symfony1)

重定向后重新提交受csrf保护的表单(Symfony1),symfony1,symfony-1.4,csrf,Symfony1,Symfony 1.4,Csrf,为了帮助可能在会话超时之前保持表单打开的用户,我尝试在通过登录页面发送表单并重定向回表单后重新提交表单。该网站有几十个表单,所以我希望将其通用化,并应用于父表单,以便它们都能获得此功能 目前,如果他们试图提交表单,但未发现任何身份验证(即会话超时或出于测试目的,我已通过另一个选项卡注销),他们将被发送到登录页面,该页面保留post参数和参考URL,如下所示: $this->getUser()->setAttribute('referer', $this->getRequest

为了帮助可能在会话超时之前保持表单打开的用户,我尝试在通过登录页面发送表单并重定向回表单后重新提交表单。该网站有几十个表单,所以我希望将其通用化,并应用于父表单,以便它们都能获得此功能

目前,如果他们试图提交表单,但未发现任何身份验证(即会话超时或出于测试目的,我已通过另一个选项卡注销),他们将被发送到登录页面,该页面保留post参数和参考URL,如下所示:

 $this->getUser()->setAttribute('referer', $this->getRequest()->getUri());
 $this->getUser()->setAttribute('postparameters', $this->getRequest()->getPostParameters());
然后,如果他们成功登录,他们将被重定向到URL

 $this->redirect($this->getUser()->getAttribute('referer', '@homepage'));
我无法在这里还原post参数,因为这是一个重定向,会导致http GET请求。因此,我将此代码放在将要处理表单的操作中

$postparams = $this->getUser()->getAttribute('postparameters');
if (is_array($postparams))
{
    foreach($postparams as $key => $postparam)
    {
        $request->setParameter($key, $postparam);
    }
} 

但是,post参数包括来自上一个会话的_csrf_令牌,表单验证失败。如果我从$postparams数组中删除该项,则表单将被拒绝,因为需要令牌。我不想完全禁用CSRF保护,但我可以找到解决方法。

我现在的解决方案是在发现表单无效并即将重新绘制后生成新的CSRF令牌

public function executeUpdate(sfWebRequest $request)
{

    ...

    if ($this->largePlantForm->isValid())
    {
        ....
    } else {        
        $tempform = new largePlantForm();
        $this->largePlantForm->setValue($tempform->getCSRFFieldName(), $tempform->getCSRFToken());
        $this->setTemplate('edit');
} 
这取决于对BaseForm的更改,该更改添加了setValue()。在表单被宣布无效后,我之所以这样称呼它,是因为事先这样做意味着csrf_令牌始终是有效的,因此毫无价值。使用我的方法,用户将被发送回他们在被定向到登录页面之前所在的表单,他们的值都在那里,他们需要查看页面并将其与新的csrf_令牌一起提交