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

时间:2013-09-03 23:24:35

标签: symfony1 symfony-1.4 csrf

为了帮助可能会暂停表单直到会话超时的用户,我尝试在通过登录页面发送表单并重定向回表单后重新提交表单。该网站有几十种表格,所以我希望这个通用并适用于父表单,这样他们都可以获得这个功能。

目前,如果他们尝试提交表单并且未找到任何身份验证(即会话超时或出于测试目的,我已通过其他选项卡注销),则会将其发送到登录页面,该页面会保留帖子参数和引荐来源网址这样:

 $this->getUser()->setAttribute('referer', $this->getRequest()->getUri());
 $this->getUser()->setAttribute('postparameters', $this->getRequest()->getPostParameters());

然后,如果他们成功登录,则会将其重定向到URL

 $this->redirect($this->getUser()->getAttribute('referer', '@homepage'));

我无法在此恢复帖子参数,因为它是重定向并导致http GET请求。因此,我已将此代码放入将要处理表单的操作

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

但是,post参数包含上一个会话中的_csrf_token,并且表单验证失败。如果我从$ postparams数组中删除该项,表单将被拒绝,因为该标记是必需的。我不想完全禁用CSRF保护,但我可以“找到解决方法。”

1 个答案:

答案 0 :(得分:0)

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

public function executeUpdate(sfWebRequest $request)
{

    ...

    if ($this->largePlantForm->isValid())
    {
        ....
    } else {        
        $tempform = new largePlantForm();
        $this->largePlantForm->setValue($tempform->getCSRFFieldName(), $tempform->getCSRFToken());
        $this->setTemplate('edit');
} 

这取决于对添加setValue()的BaseForm的更改。我在表单声明无效之后调用它的原因是,事先这样做意味着csrf_token总是有效且因此毫无价值。使用我的方法,用户被发送回他们所在的表单,然后被定向到登录页面并且他们的值都在那里,他们需要查看页面并将其与新的csrf_token一起提交。