我发现 CakePHP 中的安全组件通过将标记作为隐藏值添加到表单来帮助防止 CSRF。
我想知道是否有任何方法可以防止使用此组件或其他一些组件/帮助程序提交重复的表单?
在以前的项目中,我使用了保存在会话中的唯一哈希,在提交时读取然后删除。重复提交将具有相同的哈希值并且会产生错误。
谢谢
我已经放置了禁用按钮的 onClick 事件,如下所示:
<?= $this->Form->button('Salvar', [
'value' =>'Submit',
'onClick' => 'form.submit();this.disabled=true'
])
?>
您可以在 Cake 中实现与以前相同类型的东西。
在提交时,设置一个会话变量,将该表单标记为已提交。确保在它之后加上到期时间(几秒钟内就可以了)。如果在您处理表单时会话变量存在(并且您在过期时间内),那么您需要重新提交,所以不要保存表单数据。
我建议在模型的 save(..) 方法中执行此操作,因此您不必担心将其添加到多个代码位置。
CakePHP 2.x 中的安全组件有一个特性,允许您选择使用相同的安全令牌直到它过期或只使用一次。把它放在你的控制器 beforeFilter 方法中:
$this->Security->csrfUseOnce = true;
在此处查找更多信息
@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 安全组件
就做PRG Pattern ..很简单吧?!好吧,至少每个人都是这么说的,但没有人给出明确的答案!我花了一周的时间搜索和挖掘,然后“新手”决定自己做点什么!这是在 cakephp 中执行此操作的一种方法(我使用 2.0.5):
无论代码如何,这里的逻辑步骤都是:
1- 设置数据
2- 验证(还不要创建())
3- 将 $this->request->data 写入会话变量
4- 重定向到 saveData 操作
内部 saveData 操作:
5- 读取并保存会话变量
6- 删除会话变量
7- create()
8- 将数据保存到模型
9- 重定向
这是您的代码可能看起来如何的示例。
**收件人:“ 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'));
}
}
}
一个简单的自我重定向可能会起作用,但在大多数情况下,您希望重定向到不同的视图(例如,到另一个表单或索引视图)
我希望这种详细说明有助于节省其他人的时间,这样就不必浪费整整一周的时间(就像我的情况一样)只是为了在服务器端执行这样的功能!
不了解 cake,但尽量不在 POST 请求中显示内容,进行自我重定向。双重职位将得到解决。
安全组件应该可以工作,此外,您还可以在发布后取消设置数据:
unset($this->data['yourModel']);