ホームページ  >  記事  >  バックエンド開発  >  ThinkPHP でのフォーム トークン エラーの分析と解決

ThinkPHP でのフォーム トークン エラーの分析と解決

*文
*文オリジナル
2018-01-03 11:45:211774ブラウズ

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   = &#39;<input type="hidden" name="&#39;.$tokenName.&#39;" value="&#39;.$tokenKey.&#39;_&#39;.$tokenValue.&#39;" />&#39;;
  return $token;
}

このコードは主に、TP がフォーム検証をオンにするときに、TOKEN_NAME と現在の URI の md5 を使用してトークン値を生成するために使用されます。次に、ユーザーがフォームを送信すると、まずトークンがセッションに存在するかどうかを確認し、存在しない場合は false を返し、フォーム フィールド TOKEN_NAME で検証され、一致している場合はこれを削除します。最初にセッションを実行した場合 (次回のフォーム トークン エラーの送信を避けるため)、true を返し、それ以外の場合は false を返します。

さて、本題に戻りますが、TP

1 でフォームを送信するときにトークン エラーが発生する可能性は 2 つだけです。トークンがオンになっている場合、送信されたフォームに TOKEN_NAME フィールドが存在しないか、対応するセッションが存在しません (現在の送信フォーム環境では、対応するセッションは生成されません。これは主に、ユーザーが送信した後にエラーが報告され、同時に編集ページと表示ページが同じになるためです。メソッド)

2. セッション変数がありますが、前後の値が異なります

私たちのプロジェクトでこのエラーが発生する理由は、以下の設定を見てください

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

ブール値としては false ですが、どのヒーローがそれを文字列として任意に false として書いたかはわかりません。その後、判断するときはもちろん、フォーム トークンを開くロジックに基づいて、プロジェクト内で次のように追加します。編集と表示はすべて同じ方法です。検証エラーが発生すると、一般的なプログラムの処理ロジックは元のインターフェイスに戻ります。そのため、前回と同じフォームになります。はい、同じフォームを継続して送信することは、繰り返し送信したことに相当します。その場合、「フォームトークンエラー」が報告されます。

関連する推奨事項:

ThinkPHP の動作拡張機能とプラグインの詳細な説明

ThinkPHP が検証コードを生成および検証する方法の詳細な説明

thinkphp5 URLの例詳細説明およびルーティング関数

以上がThinkPHP でのフォーム トークン エラーの分析と解決の詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。

声明:
この記事の内容はネチズンが自主的に寄稿したものであり、著作権は原著者に帰属します。このサイトは、それに相当する法的責任を負いません。盗作または侵害の疑いのあるコンテンツを見つけた場合は、admin@php.cn までご連絡ください。