首页 > 技术 > ThinkPHP表单令牌验证功能,表单令牌错误

ThinkPHP表单令牌验证功能,表单令牌错误

2011年11月28日 发表评论 阅读评论

用thinkphp编写的带有form表单的页面,如果你打开两次同一个表单,以第一次找开的提交信息,他就会提示你“表单令牌错误”的信息!

解决办法:

官方文档上的很详细了!

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)){

// 令牌验证错误

}

 

下面看一下它是怎么生成的,如果你开启了表单令牌。

/core/model.class.php

// 自动表单令牌验证
    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;
    }

表单令牌是由下面的代码生成的。

/core/view.class.php

/**
     +----------------------------------------------------------
     * 创建表单令牌隐藏域
     +----------------------------------------------------------
     * @access private
     +----------------------------------------------------------
     * @return string
     +----------------------------------------------------------
     */
    private function buildFormToken() {
        // 开启表单验证自动生成表单令牌
        $tokenName   = C('TOKEN_NAME');
        $tokenType = C('TOKEN_TYPE');
        $tokenValue = $tokenType(microtime(TRUE));
        $token   =  '<input type="hidden" name="'.$tokenName.'" value="'.$tokenValue.'" />';
        $_SESSION[$tokenName]  =  $tokenValue;
        return $token;
    }
————————————————————
microtime -- 返回当前 Unix 时间戳和微秒数
说明mixed microtime ( [bool get_as_float] )

microtime() 当前 Unix 时间戳以及微秒数。本函数仅在支持 gettimeofday() 系统调用的操作系统下可用。

如果调用时不带可选参数,本函数以 "msec sec" 的格式返回一个字符串,其中 sec 是自 Unix 纪元(0:00:00 January 1, 1970 GMT)起到现在的秒数,msec 是微秒部分。字符串的两部分都是以秒为单位返回的。

如果给出了 get_as_float 参数并且其值等价于 TRUEmicrotime() 将返回一个浮点数。

分类: 技术 标签:
  1. 2016年9月5日15:15 | #1

    3213

  1. 本文目前尚无任何 trackbacks 和 pingbacks.