我发现CakePHP中的安全组件通过将标记添加为表单的隐藏值来帮助防止CSRF。
我想知道的是,是否有任何方法可以防止使用此组件或其他组件/助手重复提交表单?
在之前的项目中,我使用了一个保存在会话中的唯一哈希值,该哈希值在提交时被读取然后被删除。重复提交将具有相同的哈希,并且将产生错误。
感谢
答案 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'));
}
如果没有重定向,您仍然可以提交双重表单。
答案 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']);