如何防止在 PHP 中多次单击时提交多个表单
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/4614052/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
How to prevent multiple form submission on multiple clicks in PHP
提问by Marcel
How to prevent multiple form submission on multiple clicks in PHP
如何防止在 PHP 中多次单击时提交多个表单
回答by Arkh
Use a unique token generated each time you display a form and which can be used only one time; it is also usefull to prevent CSRFand replayattacks. A little example :
使用每次显示表单时生成的唯一令牌,该令牌只能使用一次;它也有助于防止CSRF和重放攻击。一个小例子:
<?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>
Combine it with a redirect so you keep a perfect backward and forward behavior. See the POST / redirect / GETpattern for more information about the redirect.
将它与重定向相结合,这样您就可以保持完美的向后和向前行为。有关重定向的更多信息,请参阅POST/redirect/GET模式。
回答by xil3
You could disable the button after the first click (using JavaScript) and also have a check on the back-end (just in-case they disabled their JavaScript) which checks if they just recently submitted.
您可以在第一次点击后禁用按钮(使用 JavaScript),还可以检查后端(以防万一他们禁用了他们的 JavaScript),检查他们是否刚刚提交。
There are quite a few different ways of doing the check on the back-end. One way would be to set a session variable when they click it the first time, which can let the system know that it's processing. If they click a second, third or fourth time, then it can just check the session variable, and if that indicates that it's already been clicked, it won't process.
有很多不同的方法可以在后端进行检查。一种方法是在他们第一次单击时设置会话变量,这可以让系统知道它正在处理。如果他们第二次、第三次或第四次点击,那么它可以只检查会话变量,如果这表明它已经被点击,则不会处理。
That's just one example - you could use that as a start.
这只是一个例子——你可以把它作为一个开始。
回答by user562374
I recommend against disabling the submit button, because in case of a temporary network issue (i.e. the request has not gone through at all), if the user chooses to abort the submission (Esc key/Stop button), he cannot submit again once network service has been restored, and instead will have to reload the page and fill in allthe form entries again.
我建议不要禁用提交按钮,因为在临时网络问题(即请求根本没有通过)的情况下,如果用户选择中止提交(Esc 键/停止按钮),他将无法再次提交网络服务已恢复,而是必须重新加载页面并再次填写所有表单条目。
回答by Mike
You could add something like this
你可以添加这样的东西
<input type="hidden" name="form-token" value="someRandomNumber">
<input type="hidden" name="form-token" value="someRandomNumber">
Then on the back-end, you have a save way of identifying multiple form submissions. This solution, of course, has some baggage since you have to delete form-tokens you know have finished processing, etc...
然后在后端,您有一种识别多个表单提交的保存方式。当然,这个解决方案有一些包袱,因为你必须删除你知道已经完成处理的表单标记等等......
In most cases, a disabled form does the trick, for instance by either disabling the button or by adding return false
to the form submit event (not sure if this works without jQuery though).
在大多数情况下,禁用的表单可以解决问题,例如通过禁用按钮或添加return false
到表单提交事件(不确定这在没有 jQuery 的情况下是否有效)。
回答by Carolyn
Can you just hide the button on click? It wouldn't effect form processing (as I know the problem is with immediately disabling the button) but it would essentially do the same thing. If you're really worried about it you could even just show another button that doesn't actually do anything. Might be an unconventional work-around, but a work-around nonetheless.
你能在点击时隐藏按钮吗?它不会影响表单处理(因为我知道问题在于立即禁用按钮)但它本质上会做同样的事情。如果您真的很担心它,您甚至可以只显示另一个实际上没有任何作用的按钮。可能是一种非常规的解决方法,但仍然是一种解决方法。
回答by Robert Sinclair
I'm doing the following on the action.php
我正在对 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
}
Note: Always initiate your sessions in the header using session_start();
注意:始终使用 session_start() 在标题中启动会话;
回答by tecHsaHiD
You can as well prevent this by having a unique field like email/username or registration number. Then test then new field against the existing one in the DB, and if it matches, then the user has registered before, and form submission should stop, otherwise continue submitting form.
您也可以通过使用唯一字段(如电子邮件/用户名或注册号)来防止这种情况发生。然后针对数据库中的现有字段测试然后新字段,如果匹配,则用户之前已经注册,并且应该停止表单提交,否则继续提交表单。
回答by Paulo Rodrigues
This is the most commom answer to your problem
这是您问题的最常见答案
if (isset($_COOKIE['FormSubmitted']))
{
die('You may only submit this form once per session!');
}