2011-01-06 180 views
12

如何防止多次点击多个表单提交的PHP如何防止多次点击多个表单提交的PHP

+2

禁用提交按钮! – 2011-01-06 10:45:21

+1

由于问题是关于服务器端行为(PHP),我建议看看下面的问题:http://stackoverflow.com/questions/218907/how-to-handle-multiple-submissions-server-side – Kel 2011-01-06 10:49:23

+4

`` – karim79 2011-01-06 10:50:35

回答

5

你可以(使用JavaScript)首次点击后,关闭按钮,也对后面的检查(只是在他们禁用JavaScript的情况下),检查它们是否刚刚提交。

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

这只是一个例子 - 你可以用它作为开始。

30

使用每次显示表单时只能使用一次的唯一标记;防止CSRFreplay攻击也是有用的。 一个小例子:

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

1

您可以添加这样的事情

<input type="hidden" name="form-token" value="someRandomNumber">

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

在大多数情况下,禁用的表单可以做到这一点,例如通过禁用按钮或通过添加return false到表单提交事件(不知道这是否工作没有jQuery虽然)。

1

我建议不要禁用提交按钮,因为如果出现临时性网络问题(即请求根本没有经过),如果用户选择中止提交(Esc键/停止按钮),他不能在网络服务恢复后再次提交,而不得不重新加载页面并再次填写全部表单条目。

0

这是最黎民回答您的问题

0

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