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
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())); }
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; } ……省略…… }
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; }
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 = '<input type="hidden" name="'.$tokenName.'" value="'.$tokenKey.'_'.$tokenValue.'" />'; return $token; }
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 ( 'TOKEN_ON' => 'false', 'TOKEN_NAME' => '__hash__', 'TOKEN_TYPE' => 'md5', 'TOKEN_RESET' => 'true', 'DB_FIELDTYPE_CHECK' => 'true' );
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!