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 相关文章推荐
Win2000+Apache+MySql+PHP4+PERL安装使用小结
Oct 09 PHP
用PHP读取IMAP邮件
Oct 09 PHP
用PHP查询域名状态whois的类
Nov 25 PHP
PHP与SQL注入攻击[三]
Apr 17 PHP
用mysql内存表来代替php session的类
Feb 01 PHP
PHP图片处理类 phpThumb参数用法介绍
Mar 11 PHP
探讨php中header的用法详解
Jun 07 PHP
Codeigniter整合Tank Auth权限类库详解
Jun 12 PHP
PHP获取一段文本显示点阵宽度和高度的方法
Mar 12 PHP
php项目中百度 UEditor 简单安装调试和调用
Jul 15 PHP
php获取ajax的headers方法与内容实例
Dec 27 PHP
Windows平台PHP+IECapt实现网页批量截图并创建缩略图功能详解
Aug 02 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
迁移PHP版本到PHP7
2015/02/06 PHP
PHP实现的各类hash算法长度及性能测试实例
2017/08/27 PHP
js 实现日期灵活格式化的小例子
2013/07/14 Javascript
jQuery实现的网页换肤效果示例
2016/09/20 Javascript
原生js仿jquery一些常用方法(必看篇)
2016/09/20 Javascript
js判断用户是输入的地址请求的路径(实例讲解)
2017/07/18 Javascript
JavaScript取得gridview中获取checkbox选中的值
2017/07/24 Javascript
通过V8源码看一个关于JS数组排序的诡异问题
2017/08/14 Javascript
select自定义小三角样式代码(实用总结)
2017/08/18 Javascript
JavaScript实现随机点名器实例详解
2019/05/07 Javascript
在vue+element ui框架里实现lodash的debounce防抖
2019/11/13 Javascript
关于AngularJS中几种Providers的区别总结
2020/05/17 Javascript
vue v-for 点击当前行,获取当前行数据及event当前事件对象的操作
2020/09/10 Javascript
openlayers实现地图测距测面
2020/09/25 Javascript
[01:02:34]TFT vs VGJ.T Supermajor 败者组 BO3 第二场 6.5
2018/06/06 DOTA
在Linux上安装Python的Flask框架和创建第一个app实例的教程
2015/03/30 Python
详尽讲述用Python的Django框架测试驱动开发的教程
2015/04/22 Python
python利用urllib实现爬取京东网站商品图片的爬虫实例
2017/08/24 Python
Python中将dataframe转换为字典的实例
2018/04/13 Python
Python爬虫包BeautifulSoup实例(三)
2018/06/17 Python
pandas 层次化索引的实现方法
2019/07/06 Python
用Python从0开始实现一个中文拼音输入法的思路详解
2019/07/20 Python
Pytorch之contiguous的用法
2019/12/31 Python
Python函数参数分类原理详解
2020/05/28 Python
PyTorch的torch.cat用法
2020/06/28 Python
python中xlutils库用法浅析
2020/12/29 Python
使用CSS3实现字体颜色渐变的实现
2020/08/10 HTML / CSS
StringBuilder和String的区别
2015/05/18 面试题
银行见习期自我鉴定
2014/01/29 职场文书
美国探亲签证邀请信
2014/02/05 职场文书
艺校音乐专业自我鉴定范文
2014/03/01 职场文书
骨干教师培训方案
2014/05/06 职场文书
假面舞会策划方案
2014/05/29 职场文书
2014年移动公司工作总结
2014/12/08 职场文书
教师个人事迹材料
2014/12/17 职场文书
【2·13】一图读懂中国无线电发展
2022/02/18 无线电