在提交时避免PHP中的竞争条件:请不要多次单击提交!
不久前,在线应用常说“不要点击提交超过一次”,现在这句话已经不存在了,对吧?比如说,在PHP中如何防范这种情况 我正在使用的一种解决方案是在会话中放入一个变量,这样您就不能每10秒提交一次以上的页面。这样,数据库工作将完成,以便进行正常检查。显然,这感觉像是黑客攻击,而且可能是 编辑:感谢大家提供Javascript解决方案。那很好,但这是一点工作。1) 这是一个输入类型=图像,2)提交必须一直启动,直到用户说可以。基本上,这篇编辑只是我在抱怨,因为我想象在看了这些令人兴奋的东西之后,我能把它弄明白 编辑:并不是说任何人都会与Spry东西集成,但这里是我使用document.getElementByid原型的最后代码。欢迎评论在提交时避免PHP中的竞争条件:请不要多次单击提交!,php,Php,不久前,在线应用常说“不要点击提交超过一次”,现在这句话已经不存在了,对吧?比如说,在PHP中如何防范这种情况 我正在使用的一种解决方案是在会话中放入一个变量,这样您就不能每10秒提交一次以上的页面。这样,数据库工作将完成,以便进行正常检查。显然,这感觉像是黑客攻击,而且可能是 编辑:感谢大家提供Javascript解决方案。那很好,但这是一点工作。1) 这是一个输入类型=图像,2)提交必须一直启动,直到用户说可以。基本上,这篇编辑只是我在抱怨,因为我想象在看了这些令人兴奋的东西之后,我能把它弄
function onSubmitClick() {
var allValid = true;
var queue = Spry.Widget.Form.onSubmitWidgetQueue;
for (var i=0;i<queue.length; i++) {
if (!queue[i].validate()) {
allValid = false;
break;
}
}
if (allValid) {
$("theSubmitButton").disabled = true;
$("form").submit();
}
}
submitclick()上的函数{
var allValid=true;
var queue=Spry.Widget.Form.onSubmitWidgetQueue;
对于(var i=0;i来说,一个解决方案是使用Javascript立即禁用单击按钮。这显然依赖于客户端浏览器上的Javascript
服务器端技巧更好,因为如果用户编辑同一条记录两次,它将捕获多个浏览器窗口之间的竞争条件。我通常在按下提交按钮后禁用它。会话限制对直接攻击很好,但我不想在不属于它的地方混合接口逻辑。这是一个excellent是jQuery有用的示例(但您可以在任何Javascript中使用它)。添加以下代码:
$("form").submit(function() {
$(":submit",this).attr("disabled", "disabled");
});
单击一次它就会禁用提交按钮。正如其他人所指出的,您可以禁用该按钮。我更喜欢服务器端检查,尽管-JS可能被禁用,用户可能会点击刷新(尽管如果您正确使用POST,将生成警告),等等
您可以在表单中添加时间戳并在会话中跟踪它-要求发布的时间戳大于跟踪的时间戳。这将防止大多数重复发布,而不会明显影响UI。还需要注意,如果PHP检测到用户“取消”请求,它的默认行为也很重要(通过关闭浏览器,按“停止”,或者第二次按“提交”)可以停止执行脚本。如果您正在执行某种长时间的事务,这是不可取的。更多详细信息。您应该同时执行客户端和服务器端保护 客户端-禁用按钮,如cletus所述,通过jquery禁用按钮
服务器端-在表单中放置一个令牌。如果有两个提交使用相同的令牌,则忽略后者。使用这种方法,您可以避免受到攻击。我认为最好的选择是让PHP脚本首先在会话数组中设置一个标志,以指示它正在处理表单。这样,第二个请求可以e设置为等待原始请求完成(使用休眠呼叫服务器端等待标志清除) 重要的是不要过多地干扰提交按钮和过程,因为web的性质是不确定的;如果没有答案,用户可能希望再次单击,并且您不希望丢失他们的数据。如果第一个请求丢失,并且您禁用了他们提交的唯一方式,则可能会发生这种情况(并因此存储)数据
一个更简洁的解决方案是提交请求,并使用javascript显示一条消息,说“正在处理”,这样用户可以看到正在发生的事情,但不会阻止他们重新提交数据。我在使用ASP.NET AJAX时使用javascript做了一个简单的版本,但在任何情况下都应该可以在您的按钮具有实际ID之前 我在button onclick事件中执行以下步骤:
closureId
中,我可以稍后通过闭包引用该变量setTimeout
函数在指定的毫秒数(5000ms=5秒)后执行动态定义的回调closureId
,并在超时后重新启用按钮嗯,这是一个辅助控件,对吗?我的意思是,这不是一个UI问题:如果有两个提交出于任何原因,你想限制它们。在你真正控制用户的计算机之前……这是一个UI决定,因为允许表单重新提交是一个问题。这可能还与用户没有获得足够的反馈有关这是一个正在处理的东西——又是一个UI故障。我还不确定我在想什么……我确实认为你进入了用户的头脑,并假设他或她是合乎逻辑的,但事实并非如此。另一方面,你必须假设UI正在运行……这不是合乎逻辑的——这是很自然的。如果你不给用户反馈,他会怀疑他是否使用了表单发送或未发送-导致他再次尝试提交。通常是连接速度慢和延迟的问题。真的,Eran,你对这个UI案例的看法是正确的。如果UI设计不正确,用户应该再次单击,这不是我们想要的。是的,我想说:我真的需要JQuery来禁用一个有id的东西吗?一直都喜欢这样$(thinger,虽然…,你也可以使用普通javascript来做,正如cletus提到的是的,普通JS也可以做,但是(imho)jQuery要优雅得多。首先,上面的代码片段可以放在标准包含的Javascript文件中,而不是散落在HTML中,它可以在任何形式上工作。+1-像jQuery或Prototype这样的库可以节省大量时间,并允许您添加所有排序