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 array_intersect()函数使用代码
Jan 14 PHP
PHP+ajax 无刷新删除数据
Feb 20 PHP
腾讯QQ php程序员面试题目整理
Jun 08 PHP
解析PHP 使用curl提交json格式数据
Jun 29 PHP
ThinkPHP3.1新特性之内容解析输出详解
Jun 19 PHP
PHP面向对象精要总结
Nov 07 PHP
thinkphp微信开发(消息加密解密)
Dec 02 PHP
PHP 读取文本文件内容并分页显示
Jan 02 PHP
PHP入门教程之字符串处理技巧总结(转换,过滤,解析,查找,截取,替换等)
Sep 11 PHP
thinkPHP中验证码的简单实现方法
Dec 05 PHP
PHP使用Redis长连接的方法详解
Feb 12 PHP
ThinkPHP框架获取最后一次执行SQL语句及变量调试简单操作示例
Jun 13 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生成二维码的两个方法和实例
2014/07/01 PHP
php自定义hash函数实例
2015/05/05 PHP
Yii2中设置与获取别名的函数(setAlias和getAlias)用法分析
2016/07/25 PHP
Display SQL Server Version Information
2007/06/21 Javascript
Javascript 实现TreeView CheckBox全选效果
2010/01/11 Javascript
jQuery动态添加的元素绑定事件处理函数代码
2011/08/02 Javascript
JQuery文本改变触发事件如聚焦事件、失焦事件
2014/01/15 Javascript
究竟什么是Node.js?Node.js有什么好处?
2015/05/29 Javascript
JS实现表单中checkbox对勾选中增加边框显示效果
2015/08/21 Javascript
深入剖析JavaScript面向对象编程
2016/07/12 Javascript
总结十个Angular.js由浅入深的面试问题
2016/08/26 Javascript
HTML5 canvas 9绘制图片实例详解
2016/09/06 Javascript
基于Vue实现支持按周切换的日历
2020/09/24 Javascript
使用socket.io制做简易WEB聊天室
2018/01/02 Javascript
ES6 更易于继承的类语法的使用
2019/02/11 Javascript
JS实现点击生成UUID的方法完整实例【基于jQuery】
2019/06/12 jQuery
如何自定义微信小程序tabbar上边框的颜色
2019/07/09 Javascript
JS中的算法与数据结构之常见排序(Sort)算法详解
2019/08/16 Javascript
vue把输入框的内容添加到页面的实例讲解
2019/11/11 Javascript
Python中with及contextlib的用法详解
2017/06/08 Python
Python Flask-web表单使用详解
2017/11/18 Python
Python timer定时器两种常用方法解析
2020/01/20 Python
Django Channel实时推送与聊天的示例代码
2020/04/30 Python
Python爬虫与反爬虫大战
2020/07/30 Python
详解CSS3新增的背景属性
2019/12/25 HTML / CSS
GNC健安喜官方海外旗舰店:美国著名保健品牌
2017/01/04 全球购物
皮肤科医师岗位职责
2013/12/04 职场文书
《记承天寺夜游》教学反思
2014/02/16 职场文书
党员教师一句话承诺
2014/05/30 职场文书
审计局班子四风对照检查材料思想汇报
2014/10/07 职场文书
2014年机关作风建设工作总结
2014/10/23 职场文书
《牧场之国》教学反思
2016/02/22 职场文书
慰问信的写作格式及范文!
2019/06/24 职场文书
怎样做好公众演讲能力?
2019/08/28 职场文书
CSS中em的正确打开方式详解
2021/04/08 HTML / CSS
详解Go语言Slice作为函数参数的使用
2021/07/02 Golang