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开发中常用的三个表单验证函数使用小结
Mar 03 PHP
php自动加载的两种实现方法
Jun 21 PHP
PHP之COOKIE支持详解
Sep 20 PHP
使用PHP实现二分查找算法代码分享
Jun 24 PHP
PHP中获取变量的变量名的一段代码的bug分析
Jul 07 PHP
PHP 代码规范小结
Mar 08 PHP
网页上facebook分享功能具体实现
Jan 26 PHP
WordPress开发中自定义菜单的相关PHP函数使用简介
Jan 05 PHP
php实现的http请求封装示例
Nov 08 PHP
PHP函数rtrim()使用中的怪异现象分析
Feb 24 PHP
Mac下php 5升级到php 7的步骤详解
Apr 26 PHP
php基于协程实现异步的方法分析
Jul 17 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中使用全局变量的几种方法
2013/06/24 PHP
php使用标签替换的方式生成静态页面
2015/05/21 PHP
javascript实现的listview效果
2007/04/28 Javascript
利用WebBrowser彻底解决Web打印问题(包括后台打印)
2009/06/22 Javascript
JavaScript 拾漏补遗
2009/12/27 Javascript
Jquery post传递数组方法实现思路及代码
2013/04/28 Javascript
Mac地址验证的javascript代码
2013/11/09 Javascript
JS获取及设置TextArea或input文本框选择文本位置的方法
2015/03/24 Javascript
BootStrap点击下拉菜单项后显示一个新的输入框实现代码
2016/05/16 Javascript
AngularJS的ng Http Request与response格式转换方法
2016/11/07 Javascript
小程序多图列表实现性能优化的方法步骤
2019/05/28 Javascript
ant-design表单处理和常用方法及自定义验证操作
2020/10/27 Javascript
Python实现同时兼容老版和新版Socket协议的一个简单WebSocket服务器
2014/06/04 Python
有关wxpython pyqt内存占用问题分析
2014/06/09 Python
利用Python的Flask框架来构建一个简单的数字商品支付解决方案
2015/03/31 Python
python实现mysql的单引号字符串过滤方法
2015/11/14 Python
Python实现ping指定IP的示例
2018/06/04 Python
Python日期时间对象转换为字符串的实例
2018/06/22 Python
对python requests发送json格式数据的实例详解
2018/12/19 Python
Django CBV与FBV原理及实例详解
2019/08/12 Python
keras导入weights方式
2020/06/12 Python
基于Python爬取素材网站音频文件
2020/10/21 Python
css3弹性盒模型(Flexbox)详细介绍
2014/10/08 HTML / CSS
CSS3实现同时执行倾斜和旋转的动画效果
2016/10/27 HTML / CSS
传统HTML页面实现模块化加载的方法
2018/10/15 HTML / CSS
台湾前三大B2C购物网站:MOMO购物网
2017/04/27 全球购物
夏威夷灵感服装及配饰:Reyn Spooner
2018/09/18 全球购物
大专毕业生自我评价分享
2013/11/10 职场文书
化学教师自荐信范文
2013/12/28 职场文书
运动会演讲稿200字
2014/08/25 职场文书
党的群众路线专项整治方案
2014/11/03 职场文书
2014年后勤管理工作总结
2014/12/01 职场文书
优秀班主任申报材料
2014/12/16 职场文书
离婚承诺书格式范文
2015/05/04 职场文书
虎兄虎弟观后感
2015/06/12 职场文书
详解缓存穿透击穿雪崩解决方案
2021/05/28 Redis