ThinkPHP でのフォーム トークン エラーを解決するにはどうすればよいですか?この記事では、主に ThinkPHP でのフォーム トークンのエラーと解決策を紹介し、thinkPHP フォーム トークンの原理、構成、エラーの原因、および対応する解決策をより詳細に分析します。困っている友達が参考になれば幸いです。
詳細は次のとおりです:
プロジェクトの開発プロセス中、データの追加および編集時にシステムによって要求される「フォームトークンエラー」に時々遭遇しましたが、最初はあまり気にしていませんでした。今日の午後、QA がこの問題をバグ システムに指摘したので、時間があったので TP3.13 のソース コードを読んで、数分後に全体像を理解しました。
プロジェクトでフォームトークンを有効にするには、通常、設定ファイルで次の設定を行う必要があります
// 是否开启令牌验证 'TOKEN_ON' => true, // 令牌验证的表单隐藏字段名称 'TOKEN_NAME' => '__hash__', //令牌哈希验证规则 默认为MD5 'TOKEN_TYPE' => 'md5', //令牌验证出错后是否重置令牌 默认为true 'TOKEN_RESET' => true
データの編集を例に挙げると、通常、フィールドフィルタリングルールを備えたモデルと、データ検出を備えたアクションがサーバー上にあります。
$table = D('table'); if(!$table->create()){ exit($this->error($table->getError())); }
のようなコード この時、IDE上でcreate()をダブルクリックして、TPフレームワークのModel.class.phpにあるcreateメソッドを探します
/** * 创建数据对象 但不保存到数据库 * @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; } ……省略…… }
コードを見ると分かります。 autoCheckToken メソッドが検出に失敗するとエラーが報告され、このメソッドを追跡し続けます
// 自动表单令牌验证 // 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; }
このコードを読むと、最初の判定に $_SESSION[$name] があることがわかります。変数の由来は? これは、トークンの生成と TokenBuildBehavior .class.php ファイルの検索から始める必要があります
// 创建表单令牌 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; }
このコードは主に、TP がフォーム検証をオンにするときに、TOKEN_NAME と現在の URI の md5 を使用してトークン値を生成するために使用されます。次に、ユーザーがフォームを送信すると、まずトークンがセッションに存在するかどうかを確認し、存在しない場合は false を返し、フォーム フィールド TOKEN_NAME で検証され、一致している場合はこれを削除します。最初にセッションを実行した場合 (次回のフォーム トークン エラーの送信を避けるため)、true を返し、それ以外の場合は false を返します。
さて、本題に戻りますが、TP
1 でフォームを送信するときにトークン エラーが発生する可能性は 2 つだけです。トークンがオンになっている場合、送信されたフォームに TOKEN_NAME フィールドが存在しないか、対応するセッションが存在しません (現在の送信フォーム環境では、対応するセッションは生成されません。これは主に、ユーザーが送信した後にエラーが報告され、同時に編集ページと表示ページが同じになるためです。メソッド)
2. セッション変数がありますが、前後の値が異なります
私たちのプロジェクトでこのエラーが発生する理由は、以下の設定を見てください
return array ( 'TOKEN_ON' => 'false', 'TOKEN_NAME' => '__hash__', 'TOKEN_TYPE' => 'md5', 'TOKEN_RESET' => 'true', 'DB_FIELDTYPE_CHECK' => 'true' );
ブール値としては false ですが、どのヒーローがそれを文字列として任意に false として書いたかはわかりません。その後、判断するときはもちろん、フォーム トークンを開くロジックに基づいて、プロジェクト内で次のように追加します。編集と表示はすべて同じ方法です。検証エラーが発生すると、一般的なプログラムの処理ロジックは元のインターフェイスに戻ります。そのため、前回と同じフォームになります。はい、同じフォームを継続して送信することは、繰り返し送信したことに相当します。その場合、「フォームトークンエラー」が報告されます。
関連する推奨事項:
ThinkPHP が検証コードを生成および検証する方法の詳細な説明
thinkphp5 URLの例詳細説明およびルーティング関数
以上がThinkPHP でのフォーム トークン エラーの分析と解決の詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。