php防止表单重复提交的几种方法
引言
为什么要避免form表单被重复提交呢?因为不想让服务器重复处理没必要的数据,同时也是避免数据库产生重复的数据,避免表单重复提交也是让网站更安全的一种表现
什么情况下会导致表单重复提交
点击提交按钮两次
点击刷新按钮
使用浏览器后退按钮重复之前的操作,导致重复提交表单
使用浏览器历史记录重复提交表单
浏览器重复的HTTP请求
网页被恶意刷新
后端防止表单重复提交的几种解决办法
3.1原理
在from表单提交的时候,用户网络或者设备原因,有时候会导致表单的重复提交,如果数据库没有做好防范的话,容易产生不需要的数据记录,其实 一种方法是:可以在提交的时候解决这个问题,在数据库添加一个字段,每次提交上去的时候去随机修改这个字段,每次在提交操作之前去比对这个值,如果相同就允许提交,不同就不允许表单提交; 第二种方法是:服务器返回表单页面时,会先生成一个subToken保存于session,并把该subToen传给表单页面。当表单提交时会带上subToken,服务器获取表单信息判断session保存的subToken和表单提交subToken是否一致。若不一致或session的subToken为空或表单未携带subToken则不通过。首次提交表单时session的subToken与表单携带的subToken一致走正常流程,然后拦截器内会删除session保存的subToken。当再次提交表单时由于session的subToken为空则不通过。从而实现了防止表单重复提交
3.2 解决办法
(1).利用js设置按钮点击后变成灰色
点击完按钮之后变成灰色就不能点击了,用户需要再次提交表单的话就要刷新页面之后重新填写数据再提交了
<p>
<input type="”text”" name="”T1″" size="”20″">
<input type="”button”" value="”提交”" onclick="”Javascript:{this.disabled=true;document.form1.submit();}”">
</p>
(2).利用session
在session中放一个特殊标志,当表单页面被请求时,生成一个特殊的字符标志串,存在session中,同时放在表单的隐藏域里,接受处理表单数据时,检查标识字串是否存在,并立即从session中删除它,然后正常处理数据,如果发现表单提交里没有有效的标志串,这说明表单已经被提交过了,忽略这次提交,这使web应用有了更高级的XSRF保护加载提交的页面时候,生成一个随机数,存储在表单的隐藏输入框中,在接收页面的PHP代码如下
<?php
$session = Yii::app()->session;
$user_id = $this->user->id;
$sessionKey = $user_id.'_is_sending';
if(isset($session[$sessionKey])){
$first_submit_time = $session[$sessionKey];
$current_time = time();
if($current_time - $first_submit_time < 10){
$session[$sessionKey] = $current_time;
$this->response(array('status'=>1, 'msg'=>'不能在10秒钟内连续发送两次。'));
} else {
unset($session[$sessionKey]);//超过限制时间,释放session";
}
}
//第一次点击确认按钮时执行
if(!isset($session[$sessionKey])){
$session[$sessionKey] = time();
}
?>
(3).利用cookies
原理和session差不多,但是 cookies一旦用户浏览器禁用 cookies,这功能就失效了
if(isset($_POST[‘submit'])){
setCOOKIE("tempCOOKIE","",time()+30);
header("Location:".$_SERVER[PHP_SELF]);
exit();
}
if(isset($_COOKIE["tempCOOKIE"])){
setCOOKIE("tempCOOKIE","",0);
echo "您已经提交过表单";
}
(4).利用header函数跳转
一旦用户点击提交按钮,处理完数据后跳到其他页面
if (isset($_POST[‘submit'])) {
header(‘location:index.php');//处理数据后,转向到其他页面
}
(5).利用数据库来添加约束
直接在数据库里添加唯一约束或创建唯一索引,一旦发现用户重复提交了,直接抛出警告或者提示,或者只处理第一次提交的数据,这是最直接有效的方法,要求前期的数据库设计和架构要考虑周全
(6).Post/Redirect/Get模式
在提交后执行页面重定向,这就是所谓的Post-Redirect-Get (PRG)模式,简言之,当用户提交了表单后,去执行一个客户端的重定向,转到提交成功信息页面
if (isset($_POST["ction"]) && $_POST[‘action'] == "submitted") {
//处理数据,如插入数据后,立即转向到其他页面
header("location:submits_success.php");
}