ThinkPHP令牌验证实例


Posted in PHP onJune 18, 2014

ThinkPHP内置了表单令牌验证功能,可以有效防止表单的远程提交等安全防护。
表单令牌验证相关的配置参数有:

'TOKEN_ON'=>true, // 是否开启令牌验证 
'TOKEN_NAME'=>'__hash__', // 令牌验证的表单隐藏字段名称 
'TOKEN_TYPE'=>'md5', //令牌哈希验证规则 默认为MD5

如果开启表单令牌验证功能,系统会自动在带有表单的模板文件里面自动生成以TOKEN_NAME为名称的隐藏域,其值则是TOKEN_TYPE方式生成的哈希字符串,用于实现表单的自动令牌验证。

自动生成的隐藏域位于表单Form结束标志之前,如果希望自己控制隐藏域的位置,可以手动在表单页面添加__TOKEN__ 标识,系统会在输出模板的时候自动替换。如果在开启表单令牌验证的情况下,个别表单不需要使用令牌验证功能,可以在表单页面添加__NOTOKEN__,则系统会忽略当前表单的令牌验证。

如果页面中存在多个表单,建议添加__TOKEN__标识,并确保只有一个表单需要令牌验证。

模型类在创建数据对象的同时会自动进行表单令牌验证操作,如果你没有使用create方法创建数据对象的话,则需要手动调用模型的autoCheckToken方法进行表单令牌验证。如果返回false,则表示表单令牌验证错误。例如:

$User = M("User"); // 实例化User对象 
// 手动进行令牌验证 
if (!$User->autoCheckToken($_POST)){ 
// 令牌验证错误 
}

在ThinkPHP框架的View.class.php里定义了一个公共的模板替换函数

protected function templateContentReplace($content) {
 // 系统默认的特殊变量替换
 $replace = array(
 '../Public' => APP_PUBLIC_PATH,// 项目公共目录
 '__PUBLIC__' => WEB_PUBLIC_PATH,// 站点公共目录
 '__TMPL__' => APP_TMPL_PATH, // 项目模板目录
 '__ROOT__' => __ROOT__, // 当前网站地址
 '__APP__' => __APP__, // 当前项目地址
 '__UPLOAD__' => __ROOT__.'/Uploads',
 '__ACTION__' => __ACTION__, // 当前操作地址
 '__SELF__' => __SELF__, // 当前页面地址
 '__URL__' => __URL__,
 '__INFO__' => __INFO__,
 );
 if(defined('GROUP_NAME'))
 {
 $replace['__GROUP__'] = __GROUP__;// 当前项目地址
 }
 if(C('TOKEN_ON')) {
 if(strpos($content,'{__TOKEN__}')) {
 // 指定表单令牌隐藏域位置
 $replace['{__TOKEN__}'] = $this->buildFormToken();
 }elseif(strpos($content,'{__NOTOKEN__}')){
 // 标记为不需要令牌验证
 $replace['{__NOTOKEN__}'] = '';
 }elseif(preg_match('/<\/form(\s*)>/is',$content,$match)) {
 // 智能生成表单令牌隐藏域
 $replace[$match[0]] = $this->buildFormToken().$match[0];
 }
 }
 // 允许用户自定义模板的字符串替换
 if(is_array(C('TMPL_PARSE_STRING')) )
 $replace = array_merge($replace,C('TMPL_PARSE_STRING'));
 $content = str_replace(array_keys($replace),array_values($replace),$content);
 return $content;
 }

上面的if(C('TOKEN_ON'))是对令牌验证的开启状态进行判断,若开启则调用buildFormToken()方法,$_SESSION[$tokenName] = $tokenValue; 其实就是给$_SESSION['__hash__']赋值。如果不想进行令牌验证,只要在页面的</form>之前加入{__NOTOKEN__}就行了,它会被函数替换成空。

在ThinkPHP的Model.class.php类里定义了令牌的验证函数

// 表单令牌验证
 if(C('TOKEN_ON') && !$this->autoCheckToken($data)) {
 $this->error = L('_TOKEN_ERROR_');
 return false;
 }

 // 自动表单令牌验证
 public function autoCheckToken($data) {
 $name = C('TOKEN_NAME');
 if(isset($_SESSION[$name])) {
 // 当前需要令牌验证
 if(empty($data[$name]) || $_SESSION[$name] != $data[$name]) {
 // 非法提交
 return false;
 }
 // 验证完成销毁session
 unset($_SESSION[$name]);
 }
 return true;
 }
PHP 相关文章推荐
PHP生成带有雪花背景的验证码
Oct 09 PHP
PHP 数字左侧自动补0
Mar 31 PHP
PHP系列学习之日期函数使用介绍
Aug 18 PHP
探讨方法的重写(覆载)详解
Jun 08 PHP
php5.5中类级别的常量使用介绍
Oct 02 PHP
php实现加减法验证码代码
Feb 14 PHP
php判断字符串在另一个字符串位置的方法
Feb 27 PHP
PHP自带ZIP压缩、解压缩类ZipArchiv使用指南
Mar 03 PHP
PHP如何实现Unicode和Utf-8编码相互转换
Jul 29 PHP
php parse_str() 函数的定义和用法
May 23 PHP
Yii2框架中日志的使用方法分析
May 22 PHP
laravel 错误处理,接口错误返回json代码
Oct 25 PHP
Smarty局部缓存的几种方法简介
Jun 17 #PHP
smarty模板局部缓存方法使用示例
Jun 17 #PHP
CodeIgniter CLI模式简介
Jun 17 #PHP
CI框架在CLI下执行占用内存过大问题的解决方法
Jun 17 #PHP
CI框架自动加载session出现报错的解决办法
Jun 17 #PHP
Thinkphp模板中截取字符串函数简介
Jun 17 #PHP
CI框架中zip类应用示例
Jun 17 #PHP
You might like
PHPEXCEL 使用小记
2013/01/06 PHP
PHP文件上传主要代码讲解
2013/09/30 PHP
php压缩和解压缩字符串的方法
2015/03/14 PHP
PHP带节点操作的无限分类实现方法详解
2016/11/09 PHP
Yii 2.0中场景的使用教程
2017/06/02 PHP
PHP实现redis限制单ip、单用户的访问次数功能示例
2018/06/16 PHP
laravel validate 设置为中文的例子(验证提示为中文)
2019/09/29 PHP
理解JavaScript的prototype属性
2012/02/11 Javascript
JS实现状态栏跑马灯文字效果代码
2015/10/24 Javascript
js实现登录验证码
2016/12/22 Javascript
Javascript的this用法
2017/01/16 Javascript
node+koa实现数据mock接口的方法
2017/09/20 Javascript
使用axios实现上传图片进度条功能
2017/12/21 Javascript
浅谈React深度编程之受控组件与非受控组件
2017/12/26 Javascript
Angular异步变同步处理方法
2018/08/13 Javascript
Vue2.2.0+新特性整理及注意事项
2018/08/22 Javascript
vue  directive定义全局和局部指令及指令简写
2018/11/20 Javascript
一步快速解决微信小程序中textarea层级太高遮挡其他组件
2019/03/04 Javascript
微信小程序云开发之使用云存储
2019/05/17 Javascript
Vue 一键清空表单的实现方法
2020/02/07 Javascript
如何利用javascript接收json信息并进行处理
2020/08/06 Javascript
微信小程序获取当前时间及星期几的实例代码
2020/09/20 Javascript
Python3指定路径寻找符合匹配模式文件
2015/05/22 Python
python性能测量工具cProfile使用解析
2019/09/26 Python
Python输出指定字符串的方法
2020/02/06 Python
简单了解django文件下载方式
2020/02/10 Python
Move Free官方海外旗舰店:美国骨关节健康专业品牌
2017/12/06 全球购物
优衣库美国官网:UNIQLO美国
2018/04/14 全球购物
美国瑜伽服装和装备购物网站:Mukha Yoga
2019/02/22 全球购物
波兰灯具、照明和LED购物网站:Lampy.pl
2019/03/11 全球购物
大学生党员自我批评
2014/02/14 职场文书
教师演讲稿大全
2014/05/16 职场文书
企业安全生产检查制度
2015/08/06 职场文书
Vue中foreach数组与js中遍历数组的写法说明
2021/06/05 Vue.js
教你win10系统中APPCRASH事件问题解决方法
2022/07/15 数码科技
Elasticsearch6.2服务器升配后的bug(避坑指南)
2022/09/23 Servers