如何防止CakePHP中的双重/重复表单提交?

时间:2009-03-16 18:39:43

标签: php cakephp

我发现CakePHP中的安全组件通过将标记添加为表单的隐藏值来帮助防止CSRF。

我想知道的是,是否有任何方法可以防止使用此组件或其他组件/助手重复提交表单?

在之前的项目中,我使用了一个保存在会话中的唯一哈希值,该哈希值在提交时被读取然后被删除。重复提交将具有相同的哈希,并且将产生错误。

感谢

7 个答案:

答案 0 :(得分:2)

你可以像以前一样在Cake中实现相同类型的东西。

在提交时,设置一个会话变量,将该表单标记为已提交。确保在它之后放一个到期时间(在几秒钟之内就可以完成)。如果处理表单时会出现会话变量(并且您在该过期时间内),那么您将重新提交,因此请不要保存表单数据。

我建议您在模型的save(..)方法中执行此操作,因此您无需担心在多个代码位置添加它。

答案 1 :(得分:2)

安全组件CakePHP 2.x中有一项功能,允许您选择使用相同的安全令牌,直到它过期或只使用一次。 将它放在你的控制器beforeFilter方法:

$this->Security->csrfUseOnce = true;

查找更多信息here

答案 2 :(得分:2)

@DoctorFox已经用csrfUseOnce = true回答了它,但这会让你陷入黑洞,你仍然需要管理。所以对我来说完整的解决方案是:

class YourAppController extends AppController {

    public $helpers = array('Html', 'Form');
    public $components = array('Security');

    public function beforeFilter() {
        $this->Security->csrfUseOnce = true;
        $this->Security->blackHoleCallback = 'blackhole';
    } 

    public function blackhole($type) {
        $this->redirect(array('action' => 'index'));
    }

如果没有重定向,您仍然可以提交双重表单。

参考:CakePHP security component

答案 3 :(得分:2)

我已经发布了onClick事件,禁用了这样的按钮:

<?= $this->Form->button('Salvar', [
                    'value' =>'Submit', 
                    'onClick' => 'form.submit();this.disabled=true'
]) 
?>

答案 4 :(得分:1)

PRG Pattern ..这很简单吧?!好吧,至少这是每个人都说的,但没有人发布明确的答案!我花了一个星期的搜索和挖掘,然后“新手”决定自己做点什么!这是在cakephp中执行此操作的一种方法(我使用2.0.5):

无论代码如何,这里的步骤都是逻辑:
1-组数据
2-验证(不要创建()) 3-将$ this-&gt; request-&gt;数据写入会话变量
4-重定向到saveData操作

内部saveData操作:
5-读&amp;保存会话的变量
6-删除会话的变量
7-创建()
8-将数据保存到模型中 9-重定向

以下是您的代码可能如何显示的示例 ** Attn:“ ourController ”和“ ourModel

public function add() {
        if ($this->request->is('post')) {
            if (isset($this->request->data)) {
                $this->ourModel->set($this->request->data);
                if ($this->ourModel->validates()) {
                    $this->Session->write('myData', $this->request->data);
                    $this->redirect(array('controller' => 'ourController', 
                                           'action' => 'saveData',
                                           'ourModel' //optional but recommended
                                          )
                                    );
                } else {
                    $this->Session->setFlash('ourModel could not be saved.');
                     }
          }
.....//the rest of add() function
}

然后你应该被重定向(在验证时)到这个函数,它再次重定向到索引操作或逻辑带你的地方!

public function saveData($model) {
        $myData = $this->Session->read('myData');
        $this->Session->delete('myData'); //extremely important
        $this->$model->create();
        if ($this->$model->save($myData)) 
               // or $myData[$model] if you are dealing with multiple models
              {
              $this->Session->setFlash(__($model.' have been saved successfully'));
              $this->redirect(array('controller' => 'ourController',
                                    'action' => 'index'
                                    )
                               );
            } 
        } else{
            $this->Session->setFlash(__($model.' could not be saved'));
        }
        }
    }

简单的自我重定向可能有效,但在大多数情况下,您希望重定向到其他视图(例如,转换为其他形式或索引视图)

我希望这个详细说明有助于节省其他人的时间,所以不必浪费整整一周(如我的情况)只是为了在服务器端执行此类功能!

答案 5 :(得分:0)

不了解蛋糕,但尝试不在POST请求中显示内容,进行自我重定向。双职位将得到解决。

答案 6 :(得分:0)

安全组件应该可以工作,此外,您还可以在帖子之后取消设置数据:

unset($this->data['yourModel']);