如何防止在PHP中多次单击提交多个表单

时间:2011-01-06 10:43:32

标签: php button click submit

如何防止在PHP中多次点击提交多个表单

8 个答案:

答案 0 :(得分:36)

每次显示表单时使用生成的唯一标记,并且只能使用一次;它还有助于防止CSRFreplay攻击。 一个小例子:

<?php
session_start();

/**
 * Creates a token usable in a form
 * @return string
 */
function getToken(){
  $token = sha1(mt_rand());
  if(!isset($_SESSION['tokens'])){
    $_SESSION['tokens'] = array($token => 1);
  }
  else{
    $_SESSION['tokens'][$token] = 1;
  }
  return $token;
}

/**
 * Check if a token is valid. Removes it from the valid tokens list
 * @param string $token The token
 * @return bool
 */
function isTokenValid($token){
  if(!empty($_SESSION['tokens'][$token])){
    unset($_SESSION['tokens'][$token]);
    return true;
  }
  return false;
}

// Check if a form has been sent
$postedToken = filter_input(INPUT_POST, 'token');
if(!empty($postedToken)){
  if(isTokenValid($postedToken)){
    // Process form
  }
  else{
    // Do something about the error
  }
}

// Get a token for the form we're displaying
$token = getToken();
?>
<form method="post">
  <fieldset>
    <input type="hidden" name="token" value="<?php echo $token;?>"/>
    <!-- Add form content -->
  </fieldset>
</form>

将其与重定向相结合,以便保持完美的前后行为。 有关重定向的详细信息,请参阅POST / redirect / GET模式。

答案 1 :(得分:6)

您可以在第一次点击(使用JavaScript)后禁用该按钮,并检查后端(只是在他们禁用JavaScript的情况下),检查他们是否刚刚提交。

有很多不同的方法可以对后端进行检查。一种方法是在第一次点击会话变量时设置它,这可以让系统知道它正在处理。如果他们点击第二次,第三次或第四次,那么它只能检查会话变量,如果这表明它已被点击,它将不会处理。

这只是一个例子 - 您可以将其作为一个开始。

答案 2 :(得分:3)

我建议不要禁用提交按钮,因为如果出现临时网络问题(即请求根本没有通过),如果用户选择中止提交(Esc键/停止按钮),则他无法提交一旦网络服务恢复,相反,将不得不重新加载页面并再次填写所有表单条目。

答案 3 :(得分:1)

你可以添加这样的东西

<input type="hidden" name="form-token" value="someRandomNumber">

然后在后端,您可以通过自定义方式识别多个表单提交。当然,这个解决方案有一些包袱,因为你必须删除你知道已经完成处理的形式代币等等。

在大多数情况下,禁用表单可以解决问题,例如通过禁用按钮或向表单提交事件添加return false(不确定这是否可以在没有jQuery的情况下工作)。

答案 4 :(得分:0)

这是您问题的最常见答案

if (isset($_COOKIE['FormSubmitted']))
{
    die('You may only submit this form once per session!');
}

答案 5 :(得分:0)

你可以在点击时隐藏按钮吗?它不会影响表单处理(因为我知道问题是立即禁用按钮)但它基本上会做同样的事情。如果你真的很担心它,你甚至可以只显示另一个实际上没有做任何事情的按钮。可能是一个非常规的解决方案,但仍然是一个解决方案。

答案 6 :(得分:0)

我正在对action.php进行以下操作

if($_SESSION && isset($_SESSION['already_submitted'])) {

  # If already submitted just redirect to thank you page

} else {

    # If first submit then assign session value and process the form
    $_SESSION['already_submitted'] = true;

    # Process form

}

注意:请始终使用session_start()在标头中启动会话;

答案 7 :(得分:-1)

您也可以通过使用唯一字段(例如电子邮件/用户名或注册号)来防止这种情况。然后针对数据库中的现有字段测试新字段,如果匹配,则说明用户之前已经注册,并且表单提交应停止,否则继续提交表单。