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 相关文章推荐
怎么使 Mysql 数据同步
Oct 09 PHP
php防止sql注入示例分析和几种常见攻击正则表达式
Jan 12 PHP
php实现快速排序的三种方法分享
Mar 12 PHP
destoon安全设置中需要设置可写权限的目录及文件
Jun 21 PHP
使用PHP和HTML5 FormData实现无刷新文件上传教程
Sep 06 PHP
php创建和删除目录函数介绍和递归删除目录函数分享
Nov 18 PHP
PHP常用文件操作函数和简单实例分析
Jun 03 PHP
php头像上传预览实例代码
May 02 PHP
thinkPHP+phpexcel实现excel报表输出功能示例
Jun 06 PHP
PHP等比例压缩图片的实例代码
Jul 26 PHP
PHP基于cookie实现统计在线人数功能示例
Jan 16 PHP
laravel 框架结合关联查询 when()用法分析
Nov 22 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中防止恶意刷新页面的代码小结
2012/10/31 PHP
解析用PHP实现var_export的详细介绍
2013/06/20 PHP
php实现网站文件批量压缩下载功能
2015/10/28 PHP
php验证码的制作思路和实现方法
2015/11/12 PHP
yii2实现分页,带搜索的分页功能示例
2017/01/07 PHP
基于jQuery的弹出警告对话框美化插件(警告,确认和提示)
2010/06/10 Javascript
jquery简单瀑布流实现原理及ie8下测试代码
2013/01/23 Javascript
用JavaScript实现动画效果的方法
2013/07/20 Javascript
jQuery实现仿QQ空间装扮预览图片的鼠标提示效果代码
2015/10/30 Javascript
再谈javascript常见错误及解决方法
2016/09/16 Javascript
深入理解React高阶组件
2017/09/28 Javascript
浅谈angularJS2中的界面跳转方法
2018/08/31 Javascript
vue 实现在函数中触发路由跳转的示例
2018/09/01 Javascript
Vue实现动态添加或者删除对象和对象数组的操作方法
2018/09/21 Javascript
详解JavaScript中的函数、对象
2019/04/01 Javascript
vue中的v-if和v-show的区别详解
2019/09/01 Javascript
react用Redux中央仓库实现一个todolist
2019/09/29 Javascript
p5.js临摹动态图形的方法
2019/10/23 Javascript
vue集成openlayers加载geojson并实现点击弹窗教程
2020/09/24 Javascript
关于element的表单组件整理笔记
2021/02/05 Javascript
Nest.js 授权验证的方法示例
2021/02/22 Javascript
使用Python进行新浪微博的mid和url互相转换实例(10进制和62进制互算)
2014/04/25 Python
Python实现扫描局域网活动ip(扫描在线电脑)
2015/04/28 Python
python计算方程式根的方法
2015/05/07 Python
Python程序员面试题 你必须提前准备!
2018/01/16 Python
Python实现PS滤镜Fish lens图像扭曲效果示例
2018/01/29 Python
Python 读取某个目录下所有的文件实例
2018/06/23 Python
Python根据服务获取端口号的方法
2019/09/25 Python
商务日语毕业生自荐信
2013/11/23 职场文书
秦兵马俑教学反思
2014/02/07 职场文书
房屋继承公证书
2014/04/10 职场文书
主要负责人任命书
2014/06/06 职场文书
2014年英语教研组工作总结
2014/12/06 职场文书
2015年打非治违工作总结
2015/04/02 职场文书
永远是春天观后感
2015/06/12 职场文书
婚宴来宾致辞
2015/07/28 职场文书