我可以看到有几个主题是关于这个问题的,但我真的找不到一个可以应用于我的案例的解决方案。
我的问题是,当用户在我的页面上提交表单,浏览器暂停时,一些用户会在处理请求时尝试刷新页面,并在数据库中插入两次行。脚本中间有两个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怎么样?