使用哈希检查是否刷新了具有$ _POST值的页面

时间:2010-04-16 01:55:09

标签: php forms post hash form-submit

将表单发布到同一个PHP页面时,如果页面被意外刷新而不是再次提交,找到正确的方法是什么?

这就是我现在正在使用的内容:

$tmp = implode('',$_POST);
$myHash = md5($tmp);

if(isset($_SESSION["myHash"]) && $_SESSION["myHash"] == $myHash)
{
    header("Location: index.php");  // page refreshed, send user somewhere else
    die();
}
else
{
    $_SESSION["myHash"] = $myHash;
}

// continue processing...

这个解决方案有什么问题吗?

UPDATE:此方案的一个示例是在注册表中插入一行。您只希望此操作执行一次。

3 个答案:

答案 0 :(得分:2)

让我们从无法区分意外刷新有目的刷新开始。因此,您只能决定不允许刷新,换句话说,要求每个表单提交必须是唯一的。最好的方法是在表单中插入一个随机标记。

<?php
    $token = /* a randomly generated string */;
    $_SESSION['_token'] = $token;
?>
<input type="hidden" name="_token" value="<?php echo $token; ?>" />

每次提交后,您都会使会话令牌失效。如果会话中的令牌与使用表单提交的令牌不同,则可以放弃POST。

评论:您可以按项目执行此操作。例如,在SO上,您可能会打开几个问题窗口并立即回答几个问题。您可以基于每个问题制作令牌,因此用户可以同时拥有多个有效令牌,但每个问题只能有一个。

  

此方案的一个示例是在注册表中插入一行。您只希望此操作执行一次。

在这种情况下,您可能不应该过于关注实际的POST,而是关注数据的一致性。您应该为每个用户提供某种形式的唯一标识,例如他的电子邮件地址。如果地址已在数据库中注册,则不会再次注册该用户。这与用户尝试注册两次(双重提交或实际再次注册)的原因无关。

答案 1 :(得分:1)

我通常更喜欢让POST处理程序执行任何需要执行的操作,然后将用户重定向到新页面

header("Location: new-page.php");

所以他们可以刷新而不会弄乱任何东西

答案 2 :(得分:1)

将令牌与POST/REDIRECT/GET设计模式结合使用似乎是最佳解决方案。

  • 设置一次性令牌会阻止用户点击后退按钮并尝试再次提交表单。
  • 重定向用户并使用视图显示输入,如果他们愿意,可以点击刷新。