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

Posted

技术标签:

【中文标题】如何防止在 PHP 中多次单击时提交多个表单【英文标题】:How to prevent multiple form submission on multiple clicks in PHP 【发布时间】:2011-06-04 14:01:13 【问题描述】:

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

【问题讨论】:

由于问题是关于服务器端行为 (PHP),我建议查看以下问题:***.com/questions/218907/… <input type="submit" onclick="this.disabled='disabled'"/> javascript 方法是否比自动点击器更快,每秒点击次数 > 1000? How to handle multiple submissions server-side的可能重复 【参考方案1】:

您也可以通过设置一个独特的字段(例如电子邮件/用户名或注册号)来防止这种情况。然后将新字段与数据库中的现有字段进行测试,如果匹配,则用户之前已注册,表单提交应停止,否则继续提交表单。

【讨论】:

【参考方案2】:

我在 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(); 在标头中启动会话

【讨论】:

【参考方案3】:

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

【讨论】:

如果用户通过按回车键或应用程序中的某些内置 JavaScript(例如form.submit())提交表单怎么办?为确保表单不会同时重新提交两次(或多次),应该有提交的标识符并跟踪它们的完整性。如果您要生成 ID,我建议您使用这个 API (api.cloudianos.com/genToken),它以提供唯一的(用于中短期)int + char 字符串而闻名。【参考方案4】:

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

【讨论】:

【参考方案5】:

使用每次显示表单时生成的唯一令牌,并且只能使用一次;防止CSRF 和replay 攻击也很有用。 一个小例子:

<?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 模式。

【讨论】:

有人知道这段代码有什么问题吗,比如安全问题? 我认为 $postedToken = filter_input(INPUT_POST, 'token'); 上缺少过滤器【参考方案6】:

你可以添加这样的东西

&lt;input type="hidden" name="form-token" value="someRandomNumber"&gt;

然后在后端,您有一种识别多个表单提交的保存方法。当然,这个解决方案有一些包袱,因为你必须删除你知道已经完成处理的表单令牌等等......

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

【讨论】:

哦,好吧,看来我的回答有点晚了... 支持其他答案【参考方案7】:

您可以在第一次点击后禁用按钮(使用 JavaScript),还可以检查后端(以防万一他们禁用了 JavaScript)检查他们是否最近提交。

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

这只是一个示例 - 您可以以此为起点。

【讨论】:

以上是关于如何防止在 PHP 中多次单击时提交多个表单的主要内容,如果未能解决你的问题,请参考以下文章

防止表单数据无效时单击多个(提交)按钮(vee-validate)

如何防止在 PHP 中重复提交表单(跨多个窗口进行保护)?

单击按钮时如何防止表单提交? [复制]

如何防止使用php自动多次点击网站?

PHP防止表单重复提交的几种常用方法汇总

Rails 5:如何防止来自 jQuery 的多次提交