ThinkPHP5.1表单令牌Token失效问题的解决


Posted in PHP onMarch 22, 2019

前言

ThinkPHP出于安全的考虑增加了表单令牌Token,由于通过Ajax异步更新数据仅仅部分页面刷新数据,就导致了令牌Token不能得到更新,紧接着的第二次新建或更新数据(提交表单时)失败——不能通过令牌的验证。

当然了,最简单的办法就是刷新整个页面,就导致了异步刷新的无意义!在网上搜寻了很多,有好几种方法;看完觉得有一个最好:

Ajax异步动态请求创建新令牌并更新到本地
主要思路:在每次发送表单结束后(不管成功与否)通过Ajax异步请求一个新的表单令牌并保存到表单隐藏域中,下次提交表单就使用新的表单令牌去通过。

最终的效果如下:

ThinkPHP5.1表单令牌Token失效问题的解决
V2.5.0.png

主要分成三步:

第一步:在Index控制器下创建生成Token的方法

之所以选择在Index控制器下创建,主要考虑在整个admin(后台)可以方便的引用该方法,不需要每次都根据控制器找寻相应的方法。也就是说,该方法其他控制器都可以引用!

<?php
namespace app\admin\controller;
use think\Controller;

class Index extends Valid {
 // 生成token函数
 public function getToken() {
  $request = \think\facade\Request::instance();
  echo $request->token();
 }
}

第二步:在Javascript中创建Ajax获取新令牌

由于后台生成新令牌的地址已经固定了,也就是:
/admin/Index/,因此通过jQuery的Get方法容易获取该令牌!

// 获取新Token并更新
function getNewToken() {
 $.get("/admin/Index/getToken", function(data) {
  document.getElementById("__token__").value = data;
 });
}

第三步:在Html页面中创建隐藏域保存令牌

其实在ThinkPHP的表单示例代码中已经有了该代码。页面第一次加载时的令牌Token是随着页面分配的,后面的令牌就是通过Ajax获取的!

<!-- 隐藏区域 -->
<input type="hidden" id="__token__" name="__token__" value="{$Request.token}" />

最后,我们就可以在javascript的相应提交表单的地方增加语句申请新令牌了!举例,下面的示例代码在提交后不管成功与否都申请了新的令牌。

/**
 * Ajax动态更新数据并异步刷新页面
 * @Author DuDongHua
 * @DateTime 2018-04-28T21:21:23+0800
 * @param {对象} Button  表单按钮对象
 * @param {文本} Modal  模块
 * @param {文本} Controller 控制器
 * @param {文本} Action  方法
 * @param {文本} Location Ajax加载页面的位置id
 * 使用方法:表单对象不用提交的任何设置,提交假按钮<a>设置onclick即可
 * 注意:
 *  1. 在javascript中拼接Thinkphp5的URL地址,不需要"{:url('" + Modal + "/" + Controller + "/" + Page + "')}方法
 *   只需要直接拼接地址即可,如:var MeURL = '/'+Modal+'/'+Controller+'/'+Page;
 */
function EditData(Button,Modal,Controller,Action,Location,Page){
 // 设置默认参数
 var Modal  = arguments[1] ? arguments[1] : "admin";  // 模块名
 var Controller = arguments[2] ? arguments[2] : "index";  // 控制器
 var Action  = arguments[3] ? arguments[3] : "editData"; // 方法名
 var Location = arguments[4] ? arguments[4] : "content"; // Ajax加载页面的位置id
 var Page  = arguments[5] ? arguments[5] : "index";  // Ajax加载页面控制器中的方法
 // 生成本页面的url用于更新后异步刷新
 var MeURL = '/'+Modal+'/'+Controller+'/'+Page;
 setLoaderIn(true); //打开加载图标
 // 异步请求数据
 $.ajax({
  url: '/'+Modal+'/'+Controller+'/'+Action,
  type: 'POST',
  data: $(Button).closest("form").serialize(), //表单序列化
  dataType: 'json',
  success: function(data){
   // 更新页面并提示
   // window.location.reload(); //当加载整个页面时有效但ajax更新时加载到主页
   loadAjaxHTML(MeURL,Location);
   showMsg(data.msg);
   setLoaderIn(false); //关闭加载图标
   getNewToken();  // 获取新Token
  },
  error:function(XMLHttpRequest, textStatus, errorThrown){
   showMsg(XMLHttpRequest.status+" "+XMLHttpRequest.readyState,textStatus,"red","#f60");
   getNewToken(); // 获取新Token
  }
 });
}

总结

以上就是这篇文章的全部内容了,希望本文的内容对大家的学习或者工作具有一定的参考学习价值,谢谢大家对三水点靠木的支持。

PHP 相关文章推荐
php实现网站插件机制的方法
Nov 10 PHP
PHP跨时区(UTC时间)应用解决方案
Jan 11 PHP
php数组(array)输出的三种形式详解
Jun 05 PHP
php判断文件上传类型及过滤不安全数据的方法
Dec 17 PHP
php中mysql连接方式PDO使用详解
Feb 25 PHP
php使用socket post数据到其它web服务器的方法
Jun 02 PHP
php使用Jpgraph绘制饼状图的方法
Jun 10 PHP
简单理解PHP的面向对象编程方式
May 17 PHP
Mac版PhpStorm之XAMPP整合apache服务器配置的图文教程详解
Oct 13 PHP
PHP实现判断数组是一维、二维或几维的方法
Feb 06 PHP
弹出模态框modal的实现方法及实例
Sep 19 PHP
PHP从零开始打造自己的MVC框架之入口文件实现方法详解
Jun 03 PHP
PHP iconv()函数字符编码转换的问题讲解
Mar 22 #PHP
PHP里的$_GET数组介绍
Mar 22 #PHP
PHP匿名函数(闭包函数)详解
Mar 22 #PHP
PHP利用递归函数实现无限级分类的方法
Mar 22 #PHP
用PHP的反射实现委托模式的讲解
Mar 22 #PHP
PHP读取目录树的实现方法分析
Mar 22 #PHP
针对PHP开发安全问题的相关总结
Mar 22 #PHP
You might like
新手配置 PHP 调试环境(IIS+PHP+MYSQL)
2007/01/10 PHP
thinkphp中空模板与空模块的用法实例
2014/11/26 PHP
CodeIgniter分页类pagination使用方法示例
2016/03/28 PHP
新闻内页-JS分页
2006/06/07 Javascript
JavaScript 判断浏览器类型及版本
2009/02/21 Javascript
jQuery中RadioButtonList的功能及用法实例介绍
2013/08/23 Javascript
js实现的点击数量加一可操作数据库
2014/05/09 Javascript
jQuery实现可关闭固定于底(顶)部的工具条菜单效果
2015/11/06 Javascript
Extjs4.0 ComboBox如何实现三级联动
2016/05/11 Javascript
jQuery筛选数组之grep、each、inArray、map的用法及遍历json对象
2016/06/20 Javascript
js实现简单的选项卡效果
2017/02/23 Javascript
基于JQuery和原生JavaScript实现网页定位导航特效
2017/04/03 jQuery
bootstrap表单示例代码分享
2017/05/18 Javascript
JavaScript利用fetch实现异步请求的方法实例
2017/07/26 Javascript
React如何将组件渲染到指定DOM节点详解
2017/09/08 Javascript
基于javascript中的typeof和类型判断(详解)
2017/10/27 Javascript
通过扫小程序码实现网站登陆功能
2019/08/22 Javascript
vue.config.js常用配置详解
2019/11/14 Javascript
JS实现拼图游戏
2021/01/29 Javascript
原生JS实现拖拽效果
2020/12/04 Javascript
[58:18]2018DOTA2亚洲邀请赛3月29日 小组赛B组 iG VS Mineski
2018/03/30 DOTA
Python数组遍历的简单实现方法小结
2016/04/27 Python
1 行 Python 代码快速实现 FTP 服务器
2018/01/25 Python
django ajax json的实例代码
2018/05/29 Python
pandas计数 value_counts()的使用
2019/06/24 Python
python3发送邮件需要经过代理服务器的示例代码
2019/07/25 Python
GDAL 矢量属性数据修改方式(python)
2020/03/10 Python
GUESS盖尔斯法国官网:美国时尚品牌
2016/09/23 全球购物
施华洛世奇英国官网:SWAROVSKI英国
2017/03/13 全球购物
美国婴儿用品及配件购买网站:Munchkin
2019/04/03 全球购物
体育老师的教学自我评价分享
2013/11/19 职场文书
西式婚礼证婚词
2014/01/12 职场文书
应届生自荐信
2014/06/30 职场文书
社区清明节活动总结
2014/07/04 职场文书
捐款活动总结
2014/08/27 职场文书
如何使用CocosCreator对象池
2021/04/14 Javascript