【发布时间】:2011-06-04 16:30:54
【问题描述】:
我想出了一种通过返回/前进或刷新页面来防止重复提交表单的技术。我想在这里讨论一下,我已经测试了一个不在生产环境中的样本,你能识别出哪些缺陷?
请注意,我很清楚使用表单令牌,它可以保护您免受 CSRF 攻击,并且未在以下步骤中添加。
-为每个表单生成表单ID,并将其用作表单中的隐藏字段:
$formid = microtime(true)*10000;
-在表单提交时:
从数据验证
-
计算表单字段数据的哈希
$allvals = ''; foreach($_POST as $k=>$v){ $allvals .= $v; } $formHash = sha1($allvals); -
通过与之前保存的哈希值进行比较来验证表单哈希值。会话值通过 $formid 变量绑定到每个表单。
$allowAction = true; if(isset($_SESSION['formHash'][$_POST['formid']]) && ($_SESSION['formHash'][$_POST['formid']] == $formHash)){ $allowAction = false; } - 如果未找到表单哈希,则表示这是第一次提交表单或更改表单数据。
-
如果数据保存(例如到数据库),将表单哈希保存到会话:
$_SESSION['formHash'][$_POST['formid']] = $formHash;
完整版代码: http://thebusy.me/2011/01/06/preventing-duplicate-form-submissions/
【问题讨论】:
-
考虑将您的哈希 sn-p 与
$formHash = sha1(serialize($_POST));进行基准测试。它也会散列密钥,这可能有益也可能没有。