防止表单重新提交
第一页包含一个HTML表单。 第二页 – 处理提交的数据的代码。
第一页中的表格被提交。 浏览器被redirect到第二页。 第二页处理提交的数据。
此时,如果第二页被刷新,则popup“确认表单重新提交”警报。
这可以预防吗?
人们曾经采取的方法有两种:
方法1:使用AJAX +redirect
这样,您可以使用JQuery或类似于Page2的方式在后台发布表单,而用户仍然可以看到page1的显示。 成功发布后,您将浏览器redirect到Page2。
方法2:发布+redirect到自我
这是论坛上的常用技巧。 Page1上的表单将数据发布到Page2,Page2处理数据并完成需要完成的工作,然后对其本身进行HTTPredirect。 这样浏览器记得的最后一个“动作”就是页面2上的一个简单的GET,所以表单不会在F5上重新提交。
你需要使用PRG – Post / Redirect / Get模式 ,你刚刚实现了PRG的P。 你需要redirect 。 (现在你根本不需要redirect了,看看这个 )
PRG是一个Web开发devise模式,可以防止一些重复的表单提交,这意味着提交表单(Post Request 1) – >redirect – >获取(请求2)
Under the hood
redirect状态码 – 使用HTTP 302的HTTP 1.0或使用HTTP 303的HTTP 1.1
带有redirect状态码的HTTP响应将在位置标题字段中额外提供一个URL。 用户代理(例如networking浏览器)通过该代码的响应被邀请对位置字段中指定的新URL进行第二次(否则相同的)请求。
redirect状态代码是为了确保在这种情况下,Web用户的浏览器可以安全地刷新服务器响应,而不会导致重新提交初始HTTP POST请求。
Double Submit Problem
Post/Redirect/Get Solution
资源
直接,你不能,这是一件好事。 浏览器的警报是有原因的。 这个线程应该回答你的问题:
防止后退button显示POST确认警报
build议的两个关键解决scheme是PRG模式,以及一个AJAX提交,然后是脚本重定位。
请注意,如果您的方法允许GET而不是POST提交方法,那么这将解决问题并更好地符合约定。 这些解决scheme是根据您希望/需要POST数据的假设提供的。
唯一的办法是100%确定同一个表单永远不会被提交两次,就是在每个问题中embedded一个唯一的标识符,并跟踪在服务器上提交的标识符。 如果用户备份到表单所在的页面并input新的数据,那么相同的表单将不起作用。
答案有两个部分:
-
确保重复的post不会混淆在服务器端的数据。 要做到这一点,在post中embedded一个唯一的标识符,以便您可以拒绝后续的请求服务器端。 这种模式在消息传递方面被称为幂等接收者 。
-
确保用户不会被重复提交的可能性所困扰
- POST后redirect到GET(POSTredirectGET模式)
- 禁用使用JavaScript的button
你在2下没有做任何事情将完全防止重复的提交。 人们可以非常快地点击,黑客可以发帖。 你总是需要1,如果你想绝对确定没有重复。
如果使用POST数据刷新页面,浏览器将确认您的重新提交。 如果使用GET数据,则不会显示消息。 保存提交后,您也可以将第二页redirect到没有数据的第三页。
那么我发现没有人提到这个把戏。
没有redirect,刷新时仍然可以防止表单确认。
默认情况下,表单代码是这样的:
<form method="post" action="test.php">
现在,将其更改为<form method="post" action="test.php?nonsense=1">
你会看到魔法。
我猜它是因为浏览器不会触发确认警报popup,如果它在url中获取GET方法(查询string)。
PRG模式只能防止页面刷新导致的重新提交。 这不是一个100%安全的措施。
通常,我会采取以下措施来防止重新提交:
-
客户端 – 使用JavaScript来防止重复点击一个button,这将触发表单提交。 你可以在第一次点击后禁用button。
-
服务器端 – 我将计算提交的参数的散列,并保存在会话或数据库的散列,所以当收到重复的提交,我们可以检测到重复,然后适当的响应客户端。 但是,您可以设法在客户端生成一个哈希。
在大多数情况下,这些措施可以帮助防止再次提交。
我真的很喜欢Angelin的回答。 但是,如果你在处理一些不实用的遗留代码,这种技术可能适合你。
在文件的顶部
// Protect against resubmits if (empty($_POST)) { $_POST['last_pos_sub'] = time(); } else { if (isset($_POST['last_pos_sub'])){ if ($_POST['last_pos_sub'] == $_SESSION['curr_pos_sub']) { redirect back to the file so POST data is not preserved } $_SESSION['curr_pos_sub'] = $_POST['last_pos_sub']; } }
然后在表单的最后,粘贴到last_pos_sub
,如下所示:
<input type="hidden" name="last_pos_sub" value=<?php echo $_POST['last_pos_sub']; ?>>
尝试三:
function prevent_multi_submit($excl = "validator") { $string = ""; foreach ($_POST as $key => $val) { // this test is to exclude a single variable, fe a captcha value if ($key != $excl) { $string .= $key . $val; } } if (isset($_SESSION['last'])) { if ($_SESSION['last'] === md5($string)) { return false; } else { $_SESSION['last'] = md5($string); return true; } } else { $_SESSION['last'] = md5($string); return true; } }
如何使用/例如:
if (isset($_POST)) { if ($_POST['field'] != "") { // place here the form validation and other controls if (prevent_multi_submit()) { // use the function before you call the database or etc mysql_query("INSERT INTO table..."); // or send a mail like... mail($mailto, $sub, $body); // etc } else { echo "The form is already processed"; } } else { // your error about invalid fields } }
字体: https : //www.tutdepot.com/prevent-multiple-form-submission/
我使用Chrome,你可以这样做…
1)你可以在表单提交的页面上使用它:
<?php if(isset($_POST['yourpost'])){ //your codes go here //in the end of this lines you will do this: header("Location: this same page.php"); exit; } else{ //do nothing } ?>
您的HTML代码如下
<html>....</html>