Heim  >  Artikel  >  Backend-Entwicklung  >  Analyse von Form-Token-Fehlern und Lösungen unter ThinkPHP

Analyse von Form-Token-Fehlern und Lösungen unter ThinkPHP

不言
不言Original
2018-06-07 10:31:401896Durchsuche

In diesem Artikel werden hauptsächlich Formular-Token-Fehler und -Lösungen unter ThinkPHP vorgestellt. Er analysiert die Prinzipien, Konfigurationen, Fehlerursachen und entsprechenden Lösungen von thinkPHP-Formular-Tokens im Detail.

Das Beispiel In diesem Artikel werden die Formular-Token-Fehler und Lösungen unter ThinkPHP beschrieben. Teilen Sie es allen als Referenz mit. Die Details lauten wie folgt:

Während des Entwicklungsprozesses des Projekts ist mir beim Hinzufügen und Bearbeiten von Daten gelegentlich der vom System angezeigte „Form-Token-Fehler“ aufgefallen. Ich habe dem Problem zunächst nicht viel Aufmerksamkeit geschenkt, bis ich heute Nachmittag etwas Freizeit hatte, also folgte ich dem Quellcode von TP3.13 und las ihn Minuten, ich kannte die ganze Geschichte.

Um Formular-Tokens im Projekt zu aktivieren, müssen Sie normalerweise die folgende Konfiguration in der Konfigurationsdatei vornehmen

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

Bearbeiten Sie die Daten als Beispiel: Normalerweise gibt es auf dem Server ein Modell mit Feldfilterregeln und eine Aktion mit Datenerkennungscode, z. B.

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

Zu diesem Zeitpunkt ist doppelt Klicken Sie in der IDE auf create(), um die Methode create in Model.class.php im TP-Framework zu finden.

/**
* 创建数据对象 但不保存到数据库
* @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;
  }
  ……省略……
}

Wenn Sie den Code sehen, werden Sie es verstehen dass ein Fehler gemeldet wird, wenn die autoCheckToken-Methode nicht erkannt wird, also verfolgen Sie diese Methode weiter

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

Nachdem Sie diesen Code gelesen haben, werden Sie feststellen, dass dies der Fall ist $_SESSION[$name] im ersten Urteil, woher kommt also diese Seesionsvariable? Nun, dies muss beim Generieren des Tokens beginnen. Suchen Sie die Datei 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;
}

Dieser Code wird hauptsächlich verwendet, um die Formularüberprüfung in TP zu ermöglichen. In diesem Fall wird der Tokenwert basierend auf TOKEN_NAME und dem MD5 des aktuellen URI generiert Wenn nicht, geben Sie „false“ zurück. Wenn dies der Fall ist, geben Sie „true“ zurück. Wenn es konsistent ist, geben Sie „true“ zurück .

ok, zurück zum Thema, es gibt nur zwei Möglichkeiten für Token-Fehler beim Senden von Formularen unter TP

1 Wenn das Token aktiviert ist, gibt es im übermittelten Formular keinen TOKEN_NAME Feld oder keine entsprechende Sitzung (in der aktuellen Übermittlungsformularumgebung wird keine entsprechende Sitzung generiert. Dies liegt hauptsächlich daran, dass nach dem Absenden durch den Benutzer ein Fehler gemeldet wird und der Benutzer dann die aktuelle Seite aktualisiert. Gleichzeitig werden die Bearbeitungsseite und die Anzeigeseite sind in der gleichen Methode)

2. Es gibt eine Sitzungsvariable, aber die Vorher- und Nachherwerte sind unterschiedlich

Der Grund, warum dieser Fehler in unserem Projekt auftritt, ist ersichtlich in der folgenden Konfiguration

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

Ursprünglich sollte es als boolescher Wert als falsch geschrieben werden, aber ich weiß nicht, welcher Held es als Zeichenfolge als falsch geschrieben hat. Dann basiert die Beurteilung natürlich auf der Logik des Öffnens des Formular-Tokens, und im Projekt sind die Methoden zum Hinzufügen, Bearbeiten und Anzeigen dieselben. Sobald ein Überprüfungsfehler auftritt, kehrt die allgemeine Programmverarbeitungslogik zur ursprünglichen Schnittstelle zurück , dann ist es das gleiche Formular wie beim letzten Mal. Die kontinuierliche Übermittlung desselben Formulars entspricht einer wiederholten Übermittlung, dann „Formular-Token-Fehler“.

Verwandte Empfehlungen:

Wie thinkPHP die Check-in-Funktion implementiert

ThinkPHP implementiert Excel Datenimport und -export (mit komplettem Fall)

Das obige ist der detaillierte Inhalt vonAnalyse von Form-Token-Fehlern und Lösungen unter ThinkPHP. Für weitere Informationen folgen Sie bitte anderen verwandten Artikeln auf der PHP chinesischen Website!

Stellungnahme:
Der Inhalt dieses Artikels wird freiwillig von Internetnutzern beigesteuert und das Urheberrecht liegt beim ursprünglichen Autor. Diese Website übernimmt keine entsprechende rechtliche Verantwortung. Wenn Sie Inhalte finden, bei denen der Verdacht eines Plagiats oder einer Rechtsverletzung besteht, wenden Sie sich bitte an admin@php.cn