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生成html分页列表的代码
Mar 18 PHP
asp和php下textarea提交大量数据发生丢失的解决方法
Jan 20 PHP
CodeIgniter php mvc框架 中国网站
May 26 PHP
IIS下PHP连接数据库提示mysql undefined function mysql_connect()
Jun 04 PHP
PHP5.3与5.5废弃与过期函数整理汇总
Jul 10 PHP
php实现图片上传并利用ImageMagick生成缩略图
Mar 14 PHP
PHP模板引擎Smarty内建函数foreach,foreachelse用法分析
Apr 11 PHP
PHP静态成员变量和非静态成员变量详解
Feb 14 PHP
Thinkphp事务操作实例(推荐)
Apr 01 PHP
Laravel框架路由设置与使用示例
Jun 12 PHP
php创建多级目录与级联删除文件的方法示例
Sep 12 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在页面中调用fckeditor编辑器的方法
2011/06/10 PHP
跟我学Laravel之路由
2014/10/15 PHP
php获取用户浏览器版本的方法
2015/01/03 PHP
PHP实现的文件操作类及文件下载功能示例
2016/12/24 PHP
javascript dom 基本操作小结
2010/04/11 Javascript
JQuery上传插件Uploadify使用详解及错误处理
2010/04/27 Javascript
JS打印gridview实现原理及代码
2013/02/05 Javascript
jQuery语法高亮插件支持各种程序源代码语法着色加亮
2013/04/27 Javascript
iframe中使用jquery进行查找的方法【案例分析】
2016/06/17 Javascript
js获取元素的偏移量offset简单方法(必看)
2017/07/05 Javascript
Websocket 向指定用户发消息的方法
2020/01/09 Javascript
JavaScript实现省份城市的三级联动
2020/02/11 Javascript
通过实例了解JS执行上下文运行原理
2020/06/17 Javascript
vue+axios 拦截器实现统一token的案例
2020/09/11 Javascript
浏览器JavaScript调试功能无法使用解决方案
2020/09/18 Javascript
vue移动端下拉刷新和上滑加载
2020/10/27 Javascript
Python 3中print函数的使用方法总结
2017/08/08 Python
Python实现爬虫设置代理IP和伪装成浏览器的方法分享
2018/05/07 Python
scrapy结合selenium解析动态页面的实现
2020/09/28 Python
Roots加拿大官网:加拿大休闲服饰品牌
2016/10/24 全球购物
美国地毯购买网站:Rugs USA
2019/02/23 全球购物
婚鞋、新娘鞋、礼服鞋、童鞋:Nina Shoes
2019/09/04 全球购物
杭州龙健科技笔试题.net部分笔试题
2016/01/24 面试题
建筑文秘专业个人求职信范文
2013/12/28 职场文书
弘扬雷锋精神活动演讲稿
2014/03/04 职场文书
垃圾分类的活动方案
2014/08/15 职场文书
教师自我剖析材料(群众路线)
2014/09/29 职场文书
合同和协议有什么区别?
2014/10/08 职场文书
会议开幕词
2015/01/28 职场文书
2015年电工工作总结
2015/04/10 职场文书
2015年房产经纪人工作总结
2015/05/15 职场文书
婚宴新郎致辞
2015/07/28 职场文书
导游词之香港-太平山顶
2019/10/18 职场文书
golang switch语句的灵活写法介绍
2021/05/06 Golang
React Native项目框架搭建的一些心得体会
2021/05/28 Javascript
springboot 多数据源配置不生效遇到的坑及解决
2021/11/17 Java/Android