Home > Backend Development > PHP Tutorial > Analysis and resolution of form token errors under ThinkPHP

Analysis and resolution of form token errors under ThinkPHP

*文
Release: 2023-03-19 07:18:02
Original
1806 people have browsed it

How to solve the form token error under ThinkPHP? This article mainly introduces form token errors and solutions under ThinkPHP, and analyzes the principles, configurations, error causes and corresponding solutions of thinkPHP form tokens in more detail. Friends in need can refer to it. I hope it will be helpful to everyone.

The details are as follows:

During the development process of the project, I occasionally encountered the "Form Token Error" prompted by the system when adding and editing data. I didn't pay much attention to it at first until this afternoon. QA mentioned this issue to the bug system, and happened to have some spare time, so he followed the source code of TP3.13 and read it. After a few minutes, he knew the whole story.

To enable form tokens in a project, you usually need to make the following configuration in the configuration file

// 是否开启令牌验证
'TOKEN_ON' => true,
// 令牌验证的表单隐藏字段名称
'TOKEN_NAME' => '__hash__',
//令牌哈希验证规则 默认为MD5
'TOKEN_TYPE' => 'md5',
//令牌验证出错后是否重置令牌 默认为true
'TOKEN_RESET' => true
Copy after login

Taking editing data as an example, there is usually a Model on the server side with field filtering rules and Action Write the data detection code, such as

$table = D('table');
if(!$table->create()){
  exit($this->error($table->getError()));
}
Copy after login

At this time, double-click create() on the IDE to locate the create method in Model.class.php in the TP framework

/**
* 创建数据对象 但不保存到数据库
* @access public
* @param mixed $data 创建数据
* @param string $type 状态
* @return mixed
*/
public function create($data='',$type='') {
  ……省略……
  // 表单令牌验证
  if(!$this->autoCheckToken($data)) {
    $this->error = L('_TOKEN_ERROR_');
    return false;
  }
  ……省略……
}
Copy after login

When you see the code, you will understand that an error will be reported when the autoCheckToken method fails to detect, then continue to track this method

// 自动表单令牌验证
// TODO ajax无刷新多次提交暂不能满足
public function autoCheckToken($data) {
  // 支持使用token(false) 关闭令牌验证
  // 如果在Action写了D方法,但没有对应的Model文件,那么$this->options为空
  if(isset($this->options['token']) && !$this->options['token']) return true;
  if(C('TOKEN_ON')){
    $name  = C('TOKEN_NAME');
    if(!isset($data[$name]) || !isset($_SESSION[$name])) { // 令牌数据无效
      return false;
    }
    // 令牌验证
    list($key,$value) = explode('_',$data[$name]);
    if($value && $_SESSION[$name][$key] === $value) { // 防止重复提交
      unset($_SESSION[$name][$key]); // 验证完成销毁session
      return true;
    }
    // 开启TOKEN重置
    if(C('TOKEN_RESET')) unset($_SESSION[$name][$key]);
    return false;
  }
  return true;
}
Copy after login

After reading this code, you will find that $_SESSION[$name is included in the first judgment ], then where does this seesion variable come from? This has to start when generating the token, locating the TokenBuildBehavior.class.php file

// 创建表单令牌
private function buildToken() {
  $tokenName = C('TOKEN_NAME');
  $tokenType = C('TOKEN_TYPE');
  if(!isset($_SESSION[$tokenName])) {
    $_SESSION[$tokenName] = array();
  }
  // 标识当前页面唯一性
  $tokenKey  = md5($_SERVER['REQUEST_URI']);
  if(isset($_SESSION[$tokenName][$tokenKey])) {// 相同页面不重复生成session
    $tokenValue = $_SESSION[$tokenName][$tokenKey];
  }else{
    $tokenValue = $tokenType(microtime(TRUE));
    $_SESSION[$tokenName][$tokenKey]  = $tokenValue;
  }
  $token   = &#39;<input type="hidden" name="&#39;.$tokenName.&#39;" value="&#39;.$tokenKey.&#39;_&#39;.$tokenValue.&#39;" />&#39;;
  return $token;
}
Copy after login

This code is mainly used to open the form in TP In the case of verification, the token value is generated based on TOKEN_NAME and the md5 of the current URI. When the user submits the form, first verify whether the session exists. If not, return false. If yes, then verify with the form field TOKEN_NAME. If it is consistent, delete this session first (when used to avoid the form token error in the next submission), return true, otherwise return false.

ok, back to the topic, the reason why a token error occurs when submitting a form under TP, there are only two possibilities

1. Submit when the token is turned on In the form, there is no TOKEN_NAME field or no corresponding session (in the current submission form environment, no corresponding session is generated. This is mainly because an error is reported after the user submits and the user then refreshes the current page. At the same time, the editing page and the display page are in the same Method)

2. There is a session variable, but the before and after values ​​are different

The reason why this error occurs in our project, you can look at the following configuration

return array (
  &#39;TOKEN_ON&#39; => &#39;false&#39;,
  &#39;TOKEN_NAME&#39; => &#39;__hash__&#39;,
  &#39;TOKEN_TYPE&#39; => &#39;md5&#39;,
  &#39;TOKEN_RESET&#39; => &#39;true&#39;,
  &#39;DB_FIELDTYPE_CHECK&#39; => &#39;true&#39;
);
Copy after login

It should be written as Boolean The value of false, I don’t know which hero willfully wrote it as false as a string, then of course the judgment will be based on the logic of opening the form token, and in the project, adding, editing and display are all the same method. Once verified If an error occurs, the general program processing logic will return to the original interface, then it will be the same form as last time. Continuous submission of the same form is equivalent to repeated submission, then a "form token error" will be reported.

Related recommendations:

Detailed explanation of ThinkPHP’s behavioral extensions and plug-ins

Detailed explanation of how ThinkPHP generates and verifies verification codes

Detailed explanation of thinkphp5 URL and routing functions

The above is the detailed content of Analysis and resolution of form token errors under ThinkPHP. For more information, please follow other related articles on the PHP Chinese website!

Related labels:
source:php.cn
Statement of this Website
The content of this article is voluntarily contributed by netizens, and the copyright belongs to the original author. This site does not assume corresponding legal responsibility. If you find any content suspected of plagiarism or infringement, please contact admin@php.cn
Popular Tutorials
More>
Latest Downloads
More>
Web Effects
Website Source Code
Website Materials
Front End Template