【问题标题】:Resubmit a csrf protected form after redirect (Symfony1)重定向后重新提交受 csrf 保护的表单 (Symfony1)
【发布时间】:2013-09-04 11:01:17
【问题描述】:

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

目前,如果他们尝试提交表单但未找到身份验证(即会话超时或出于测试目的,我已通过另一个选项卡注销),他们将被发送到保留帖子参数和引荐来源网址的登录页面,例如所以:

 $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_token,并且表单验证失败。如果我从 $postparams 数组中删除该项目,则表单将被拒绝,因为需要令牌。我不想完全禁用 CSRF 保护,但我找不到解决办法。

【问题讨论】:

    标签: symfony1 symfony-1.4 csrf


    【解决方案1】:

    我现在的解决办法是在发现表单无效,即将重绘后生成一个新的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 一起提交。

    【讨论】:

      猜你喜欢
      • 2013-04-13
      • 1970-01-01
      • 2016-03-15
      • 2013-08-06
      • 2016-12-30
      相关资源
      最近更新 更多