ThinkPHP防止重复提交表单的方法实例分析


Posted in PHP onMay 10, 2018

本文实例总结分析了ThinkPHP防止重复提交表单的方法。分享给大家供大家参考,具体如下:

为什么会有表单重复的坑

在开发中,如果一个新增或修改的表单,在后台完成数据库操作后我们设定的不是跳转到其他页面,还是返回本页面,这时点击浏览器的后退再提交或刷新页面,会导致form表单重复提交,即这条记录会被增加或修改两次。

导致表单重复提交的原因是:第一次提交的表单会被缓存到内存中,直到页面下次提交或页面关闭或转向其他页面时才消失。在自调用返回时,内存中的数据依然在,这时页面中的判断提交的代码依然可以检测到提交的值,顾会产生重复提交的效果。

如何解决?

总结网上的解决办法和自己的测试,可以用以下几个办法:

方法1:最简单:页面提交后转到另一个页面而不是本页面,举个栗子,比如你的页面地址为

http://yourdomain.com/User/Index/login

则该页面的表单action地址可以为另外的处理地址,如

<form action="{:U('User/Index/check_login')}" method="post">

这样报错返回,或者用户点击回退按钮,还是会回到上一个地址,不过这种情况也不保险。还要搭配方法2,一起比较保险

方法2:提交表单后提交按钮变灰/隐藏提交按钮

这种方式一般是结合方法1来做的,通过JS来动态监听用户的点击动作,动态将按钮属性置成disabeld,即为灰色不可用。代码如下:

HTML:

<form action="{:U('User/Index/check_login')}" method="post">
  <input type="text" name="username" value="" id="username" />
  <input type="password" name="userpwd" id="userpwd" />
  <input type="submit" name="login_btn" id="login_btn" value="登陆"/>
</form>

JS:

$().ready(function(){
   $("#login_btn").on('click',function(){
      $(this).attr('disabled',true);
   });
});

方法1+方法2 结合后,基本上90%以上的重复提交问题都能解决,但是大刘这里还是要说下第三种方法,即在服务端一劳永逸的解决这个问题

方法3:使用隐藏随机TOKEN值的方法进行重复提交判断

首先,在项目的functions.php中添加如下方法

//创建TOKEN
function createToken() {
  $code = chr(mt_rand(0xB0, 0xF7)) . chr(mt_rand(0xA1, 0xFE)) .    chr(mt_rand(0xB0, 0xF7)) . chr(mt_rand(0xA1, 0xFE)) . chr(mt_rand(0xB0, 0xF7)) . chr(mt_rand(0xA1, 0xFE));
  session('TOKEN', authcode($code));
}
//判断TOKEN
function checkToken($token) {
  if ($token == session('TOKEN')) {
    session('TOKEN', NULL);
    return TRUE;
  } else {
   return FALSE;
  }
}
/* 加密TOKEN */
function authcode($str) {
  $key = "YOURKEY";
  $str = substr(md5($str), 8, 10);
  return md5($key . $str);
}

在表单页面form中填入以下HTML代码

HTML:

<input type="hidden" name="TOKEN" value="{:session('TOKEN')}" />

在页面展示前调用creatToken()方法生成token,在相应控制器POST请求中 使用 checkToken() 进行判断是否重复提交

if(IS_POST)
{
$post_token = I('post.TOKEN');
 if(!checkToken($post_token)){
   $this->error('请不要重复提交页面',U('User/Index/login'));
 }
}

基本上,这3个方法配合着使用,就能解决ThinkPHP开发中表单重复提交问题,当然,有同学说可以使用ThinkPHP的令牌环机制,这样其实就更简单了,TP会默认在表单中生成一个隐藏域,到时候判断这个隐藏域是否存在以及和session中的值是否想的即可,原理和方法3是一样的。

PS:今天终于把内容用简书的markdown编辑器发出来了,果然markdown语法不是盖的,整个排版都清爽了,不错不错。

希望本文所述对大家基于ThinkPHP框架的PHP程序设计有所帮助。

PHP 相关文章推荐
用IE远程创建Mysql数据库的简易程序
Oct 09 PHP
WHOIS类的修改版
Oct 09 PHP
PHP下escape解码函数的实现方法
Aug 08 PHP
php fputcsv命令 写csv文件遇到的小问题(多维数组连接符)
May 24 PHP
xml在joomla表单中的应用详解分享
Jul 19 PHP
PHP管理内存函数 memory_get_usage()使用介绍
Sep 23 PHP
thinkphp备份数据库的方法分享
Jan 04 PHP
CodeIgniter删除和设置Cookie的方法
Apr 07 PHP
php实现的mongodb操作类
May 28 PHP
php监测数据是否成功插入到Mysql数据库的方法
Nov 25 PHP
PHP面向对象程序设计OOP继承用法入门示例
Dec 27 PHP
php并发加锁问题分析与设计代码实例讲解
Feb 26 PHP
PHP实现用户登录的案例代码
May 10 #PHP
yii2多图上传组件的使用教程
May 10 #PHP
PHP数组去重的更快实现方式分析
May 09 #PHP
PHP+MySQL实现消息队列的方法分析
May 09 #PHP
PHP共享内存使用与信号控制实例分析
May 09 #PHP
php curl批处理实现可控并发异步操作示例
May 09 #PHP
php使用curl伪造来源ip和refer的方法示例
May 08 #PHP
You might like
php支持中文字符串分割的函数
2015/05/28 PHP
php判断访问IP的方法
2015/06/19 PHP
php如何控制用户对图片的访问 PHP禁止图片盗链
2016/03/25 PHP
php 调用ffmpeg获取视频信息的简单实现
2017/04/03 PHP
Windows服务器中PHP如何安装redis扩展
2019/09/27 PHP
javascript 窗口加载蒙板 内嵌网页内容
2010/11/19 Javascript
JQuery 操作/获取table具体代码
2013/06/13 Javascript
给超链接添加特效鼠标移动展示提示信息且随鼠标移动
2013/10/17 Javascript
JavaScript生成福利彩票双色球号码
2015/05/15 Javascript
jQuery使用each方法与for语句遍历数组示例
2016/06/16 Javascript
AngularJS通过$location获取及改变当前页面的URL
2016/09/23 Javascript
Web前端开发之水印、图片验证码
2016/11/27 Javascript
EasyUI学习之Combobox下拉列表(1)
2016/12/29 Javascript
Bootstrap table简单使用总结
2017/02/15 Javascript
node.js中debug模块的简单介绍与使用
2017/04/25 Javascript
angularjs定时任务的设置与清除示例
2017/06/02 Javascript
vue指令v-html使用过滤器filters功能实例
2019/10/25 Javascript
在centos7中分布式部署pyspider
2017/05/03 Python
python脚本作为Windows服务启动代码详解
2018/02/11 Python
在Python文件中指定Python解释器的方法
2019/02/18 Python
Python创建字典的八种方式
2019/02/27 Python
如何使用python爬虫爬取要登陆的网站
2019/07/12 Python
python matplotlib库直方图绘制详解
2019/08/10 Python
pyinstaller打包成无控制台程序时运行出错(与popen冲突的解决方法)
2020/04/15 Python
Python django框架 web端视频加密的实例详解
2020/11/20 Python
HTML5进阶段内联标签汇总(小篇)
2016/07/13 HTML / CSS
如何使用canvas绘制可移动网格的示例代码
2020/12/14 HTML / CSS
Monki官网:斯堪的纳维亚的独立时尚品牌
2020/11/09 全球购物
英国礼品和生活方式品牌:Treat Republic
2020/11/21 全球购物
abstract class和interface有什么区别
2013/08/04 面试题
青年创业培训欢迎词
2014/01/08 职场文书
新年抽奖获奖感言
2014/03/02 职场文书
世界水日宣传活动总结
2015/02/09 职场文书
校运会广播稿
2015/08/19 职场文书
CentOS8.4安装Redis6.2.6的详细过程
2021/11/20 Redis
JS class语法糖的深入剖析
2022/07/07 Javascript