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时间不正确的解决方法
Apr 09 PHP
php mysql数据库操作分页类
Jun 04 PHP
php 文件上传系统手记
Oct 26 PHP
php 显示指定路径下的图片
Oct 29 PHP
供参考的 php 学习提高路线分享
Oct 23 PHP
PHP分多步骤填写发布信息的简单方法实例代码
Sep 23 PHP
Codeigniter生成Excel文档的简单方法
Jun 12 PHP
php生成短域名函数
Mar 23 PHP
WordPress开发中自定义菜单的相关PHP函数使用简介
Jan 05 PHP
CI分页类首页、尾页不显示的解决方法
Mar 28 PHP
PHP简单遍历对象示例
Sep 28 PHP
浅谈laravel数据库查询返回的数据形式
Oct 21 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
第五节 克隆 [5]
2006/10/09 PHP
PHP上传图片进行等比缩放可增加水印功能
2014/01/13 PHP
php对数组排序代码分享
2014/02/24 PHP
PHP代码优化之成员变量获取速度对比
2014/02/28 PHP
PHP简单判断字符串是否包含另一个字符串的方法
2016/03/25 PHP
来自chinaz的ajax获取评论代码
2008/05/03 Javascript
了解了这些才能开始发挥jQuery的威力
2013/10/10 Javascript
js实现上传图片预览的方法
2015/02/09 Javascript
javascript顺序加载图片的方法
2015/07/18 Javascript
JavaScript生成二维码图片小结
2015/12/27 Javascript
javascript正则表达式中分组详解
2016/07/17 Javascript
原生js实现放大镜效果
2017/01/11 Javascript
Bootstrap超大屏幕的实现代码
2017/03/22 Javascript
分析JS中this引发的bug
2017/12/12 Javascript
vue短信验证性能优化如何写入localstorage中
2018/04/25 Javascript
angularJs中$scope数据序列化的实例
2018/09/30 Javascript
微信小程序常用的3种提示弹窗实现详解
2019/09/19 Javascript
Python获取脚本所在目录的正确方法
2014/04/15 Python
python使用正则表达式分析网页中的图片并进行替换的方法
2015/03/26 Python
使用Python下的XSLT API进行web开发的简单教程
2015/04/15 Python
python使用装饰器和线程限制函数执行时间的方法
2015/04/18 Python
Python过滤列表用法实例分析
2016/04/29 Python
基于python 字符编码的理解
2017/09/02 Python
Python模拟百度自动输入搜索功能的实例
2019/02/14 Python
详解如何减少python内存的消耗
2019/08/09 Python
Django项目使用ckeditor详解(不使用admin)
2019/12/17 Python
Python常用模块sys,os,time,random功能与用法实例分析
2020/01/07 Python
pyMySQL SQL语句传参问题,单个参数或多个参数说明
2020/06/06 Python
python实现凯撒密码、凯撒加解密算法
2020/06/11 Python
通过实例解析python创建进程常用方法
2020/06/19 Python
写好自荐信的技巧
2013/11/08 职场文书
小学综合实践活动总结
2014/07/07 职场文书
2014年有孩子的离婚协议书范本
2014/10/08 职场文书
企业年检委托书范本
2014/10/14 职场文书
个人廉政承诺书
2015/04/28 职场文书
初中物理教学反思
2016/02/19 职场文书