在PHP中提交表单时如何防止多次插入?
有时,用户可能会按两次[code>Enter],然后插入两次帖子在PHP中提交表单时如何防止多次插入?,php,html,forms,form-submit,Php,Html,Forms,Form Submit,有时,用户可能会按两次[code>Enter],然后插入两次帖子 除了检查是否已经存在具有相同标题和内容的帖子之外,是否有其他解决方案可以防止这种情况发生?一旦表单提交,就使用Javascript禁用提交按钮(onsubmit) 注意,如果用户禁用了Javascript,他们仍然可以提交两次。这种情况是否经常发生,是否有理由也签入您的代码(正如您在问题中所建议的那样)取决于您。一旦用户提交表单,请使用JavaScript禁用提交按钮。例如,这就是StackOverflow在回答问题时使用的方法
除了检查是否已经存在具有相同
标题和内容的帖子之外,是否有其他解决方案可以防止这种情况发生?一旦表单提交,就使用Javascript禁用提交按钮(onsubmit
)
注意,如果用户禁用了Javascript,他们仍然可以提交两次。这种情况是否经常发生,是否有理由也签入您的代码(正如您在问题中所建议的那样)取决于您。一旦用户提交表单,请使用JavaScript禁用提交按钮。例如,这就是StackOverflow在回答问题时使用的方法
比如说
<input type="submit" onclick="this.disabled=true" />
单击按钮后,立即使用JavaScript禁用该按钮
onclick="this.disabled=true;forms[0].submit();"
按两次submit很少会导致多个插入,但如果您想要一个非常简单的解决方案,请使用
onsubmit="document.getElementById('submit').disabled = true"
在表单标签中,如果您提供提交按钮,则显示了一种不使用javascript的方式。对帖子使用唯一的标记,以便每个帖子/回发只处理一次
禁用submit按钮不是一个很好的解决方案,因为人们可能会关闭javascript,或者做其他奇怪的事情。客户端验证是一个良好的开端,但也应始终使用服务器端处理进行备份。有几种解决方案可以解决此问题:
发布表单时,使用Javascript禁用表单的提交按钮。缺点是,这绝对不是一种万无一失的方法。在不点击按钮的情况下提交表单非常容易,这对禁用JavaScript的用户也不起作用我绝对不推荐这种方法。
例如:
// form.php
<?php
// obviously this can be anything you want, as long as it is unique
$_SESSION['token'] = md5(session_id() . time());
?>
<form action="foo.php" method="post">
<input type="hidden" name="token" value="<?php echo $_SESSION['token'] ?>" />
<input type="text" name="bar" />
<input type="submit" value="Save" />
</form>
// foo.php
if (isset($_SESSION['token']))
{
if (isset($_POST['token']))
{
if ($_POST['token'] != $_SESSION['token'])
{
// double submit
}
}
}
用于将会话变量(例如$\u session['posttimer'])设置为post上的当前时间戳。在PHP中实际处理表单之前,请检查$\u session['posttimer']变量是否存在,并检查某个时间戳差异(即:2秒)。这样,您就可以很容易地过滤掉双重提交
例如:
// form.php
<?php
// obviously this can be anything you want, as long as it is unique
$_SESSION['token'] = md5(session_id() . time());
?>
<form action="foo.php" method="post">
<input type="hidden" name="token" value="<?php echo $_SESSION['token'] ?>" />
<input type="text" name="bar" />
<input type="submit" value="Save" />
</form>
// foo.php
if (isset($_SESSION['token']))
{
if (isset($_POST['token']))
{
if ($_POST['token'] != $_SESSION['token'])
{
// double submit
}
}
}
//form.html
//foo.php
如果(isset($\ U POST)和&!空($\ U POST))
{
如果(isset($_会话['posttimer']))
{
如果((time()-$\u SESSION['posttimer'])或者,使用一次性表单键。生成一个唯一的一次性使用键以与表单一起提交
依赖Javascript是一个坏主意,因为用户可能已在客户端禁用它。使用密钥方案,当服务器收到提交时,可以锁定该密钥的提交。您可以根据自己的喜好对重复提交进行响应
要使这种方法起作用,密钥必须是唯一的,并且很难预测。否则,某些表单可能会由于密钥冲突而被锁定。因此,您不必跟踪每次表单提交的密钥并避免冲突,密钥应该随着该用户的会话而过期。另一件需要注意的事情是,如果恶意用户能够预测密钥,您的代码可能容易受到某种劫持或DOS攻击。我使用以下方法:
$form_token = $_SESSION['form_token'] = md5(uniqid());
将$form_令牌与表单一起发送,然后
我检查表单\u令牌:
if($_SESSION['form_token'] != $_POST['form_token']) {
echo 'Error';
}
Aron Rotterveel的在为我工作的每篇帖子上都包含一个唯一的标记。但是,当用户刷新页面时,我的表单仍会提交(F5)。我通过添加重置来解决此问题:
// reset session token
$_SESSION['token'] = md5( $_POST['token'] . time() );
我的最终脚本如下所示:
if (isset($_SESSION['token'])) {
if (isset($_POST['token'])) {
if ($_POST['token'] != $_SESSION['token']) {
echo '<h3>Oops! You already submitted this request.</h3>';
} else {
// process form
// reset session token
$_SESSION['token'] = md5( $_POST['token'] . time() );
}
} else {
echo 'post token not set';
$_SESSION['token'] = md5( $somevariable . time() );
}
}
if(isset($\u会话['token'])){
如果(isset($_POST['token'])){
如果($\u POST['token']!=$\u会话['token']){
echo“哎呀!您已经提交了此请求。”;
}否则{
//过程形式
//重置会话令牌
$_SESSION['token']=md5($_POST['token'].time());
}
}否则{
回显“未设置post令牌”;
$\会话['token']=md5($somevariable.time());
}
}
哦!别忘了在
我是一名PHP新手,因此如果您发现异常情况,请纠正我。使用JavaScript阻止它发送另一种方法来创建确认页面,用户可以最终按下提交按钮。这可能会减少此类可能性。我正在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();
$(文档).ready(函数(){
$('#postHideBtn').show();
$('#postHideBtn')。单击(函数(){
$('#postHideBtn').hide();
});
});
如果表单是通过键盘笔划提交的,则onclick
处理程序将不会运行,例如,用户在关注提交按钮的同时按下enter键。最好像其他海报建议的那样使用onsubmit
。@asah:我确实喜欢@Mats建议的令牌想法。但是如果我们留在客户端,它实际上可能会最好有一个同时包含单击和提交的方法。在onsubmit实际启动之前,2次鼠标单击可以在IE中注册。愚蠢,但我看到了。这是我使用的方法。每当呈现页面时生成GUID,每当保存表单时将其包含在数据库中。在提交处理代码中,确保GUID在插入之前不存在于数据库中。您通常使用哪种类型的GUID生成算法?+1-这是最常用的方法,并且没有客户端依赖关系。为什么不接受此作为答案?@Steve not true。帖子不应是幂等的。如果您想知道当我们第二次单击“提交”。这是无用的代码。只需在表单提交后执行HTTP重定向。我希望这样做,但我的表单可以在一个页面中工作。我最初希望使用jquery unload(),但我发现这在用户无意中
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
}