防止在页面刷新PHP上插入重复记录


Preventing Duplicate Record Insertion on Page Refresh PHP

我可以看到有几个主题是关于这个问题的,但我真的找不到一个可以应用于我的案例的解决方案。

我的问题是,当用户在我的页面上提交表单,浏览器暂停时,一些用户会在处理请求时尝试刷新页面,并在数据库中插入两次行。脚本中间有两个curl调用,可能需要几秒钟才能完成,这就是导致延迟的原因。我相信,通过刷新页面,他们打开了一个具有相同会话详细信息的新连接,并再次提交,但被放弃的后端脚本仍在处理中。最重要(也是最糟糕)的是,表单本身就发布了。

我们试图应用几种措施(清除SESSION以跟踪生成的会话变量等)。我认为表单上的隐藏字段不是一种选择,因为流程脚本可能会被伪造的浏览器攻击。

我的建议是将流程部分从视图中分离出来,并将其迁移到单独的脚本中,然后通过Ajax调用它。当Ajax被调用时,禁用提交按钮会提示用户在处理页面时不要刷新页面。这样,即使他们刷新了页面,也不会再次提交,到那时,进程可以设置SESSION变量以防止重新提交。

你对这个解决方案有什么看法?

不要向我发布流程中这样或那样不好的事情,并更改这个或那个,因为我无法在整个系统的基础上对流程进行任何重大更改。

非常感谢。

///////////////////////////////////////////////////////////////////////////

扩展:

  • 将自发布怪物脚本的流程部分迁移到Ajax中
  • ajax启动后,我禁用提交按钮,并显示一个带有文本的微调器。不要刷新浏览器
  • 当Ajax脚本中的操作完成时,我设置了一个会话变量,指示进程已经完成
  • 如果他们仍然刷新浏览器,表单数据就会被清除,他们根本没有足够的时间再次填写,所以当他们再次提交表单时,会话变量已经设置好,按下提交按钮时,他们会收到一条消息,然后重定向到确认页面

到目前为止,它似乎运行良好,进行了几次测试。

你们觉得这个解决方案怎么样?是否存在漏洞或安全隐患?(错误消息通过Json来自脚本)

好吧,另一个选择:

<?php
   session_start();
   $old_session_exists = false;
   while (isset($_SESSION['processing-'.$_SERVER['REMOTE_ADDR'].$_SERVER['HTTP_USER_AGENT']])) {
      $old_session_exists = true;
      sleep(5);
   }
   if (!$old_session_exists) {
      // process your cURL and save output into another session variable
      $_SESSION['processing-'.$_SERVER['REMOTE_ADDR'].$_SERVER['HTTP_USER_AGENT']] = 1;
      $_SESSION['result-'.$_SERVER['REMOTE_ADDR'].$_SERVER['HTTP_USER_AGENT']] = cURL(...);
      // remove processing session
      unset($_SESSION['processing-'.$_SERVER['REMOTE_ADDR'].$_SERVER['HTTP_USER_AGENT']]);
   }
   // return the result from session
   $ret = $_SESSION['result-'.$_SERVER['REMOTE_ADDR'].$_SERVER['HTTP_USER_AGENT']];
   unset($_SESSION['result-'.$_SERVER['REMOTE_ADDR'].$_SERVER['HTTP_USER_AGENT']]);
   return / echo $ret;
?>

gergiusz:

我对解决方案的看法将取决于你到底在发送什么(例如,使用经典的方法,你不应该能够通过JS请求发送文件)。此外,使用Ajax会使应用程序依赖于启用JS,这会是个问题吗?。最后,即使小心,请求也可能是伪造的。。。

鉴于此,我的观点是"请不要"。我认为这给事情增加了不必要的复杂性。

尽管邪恶肮脏,你有没有试过把它藏起来?。这是一个典型的解决方案,允许您在提交表单后立即显示"请稍候"消息。就像所有东西一样,它可以被锻造和破碎,但话说回来,什么不是?。

使用异步cURL怎么样?