Heim >php教程 >PHP开发 >Analyse des Problems des Sitzungsschreibfehlers, der durch die Erweiterung der standardmäßigen Sitzungs-Middleware von Laravel verursacht wird

Analyse des Problems des Sitzungsschreibfehlers, der durch die Erweiterung der standardmäßigen Sitzungs-Middleware von Laravel verursacht wird

高洛峰
高洛峰Original
2016-12-27 10:04:121081Durchsuche

Aufgrund der jüngsten Projektentwicklungsanforderungen verwenden der mobile Client und der Webclient einen einheitlichen Satz von Schnittstellen. Um sicherzustellen, dass die Sitzung unter verschiedenen Umständen normal und kompatibel sein kann, hoffe ich, die Methode zum Abrufen der Sitzungs-ID zu ändern. Standardmäßig werden alle Websites über das Cookie im Header-Header der HTTP-Anfrage implementiert, und die im Cookie angegebene SessionID wird mit den entsprechenden Daten auf der Serverseite verknüpft, um die Sitzungsfunktion zu implementieren.

Für mobile Clients wird das ursprüngliche Cookie jedoch möglicherweise nicht unterstützt oder je nach Plattformanforderungen blockiert. Daher erfordert die Entwicklung das Hinzufügen eines Anforderungsheaders X-Session-Token zur Identifizierung der SessionID. Im Laravel-Framework werden die Sitzungsinitialisierung, das Lesen und Starten alle über die IlluminateSessionMiddlewareStartSession-Middleware implementiert. Diese Middleware verfügt über eine Schlüsselmethode getSession. Diese Methode dient dazu, die SessionId abzurufen und der Sitzungskomponente mitzuteilen, welche Anmeldeinformationen zum Wiederherstellen der Sitzungsdaten verwendet werden sollen.

Diese Middleware ist unter der Datei app/Http/Kernel.php registriert.

Ich habe eine neue Klasse zum Erben der Middleware erstellt und den Registrierungsort unter app/Http/Kernel.php ersetzt. Der ursprüngliche Quellcode der getSession-Methode lautet wie folgt:

public function getSession(Request $request)
{
$session = $this->manager->driver();
$session->setId($request->cookies->get($session->getName()));
return $session;
}

In Die neue Middleware habe ich geändert in:

public function getSession(Request $request)
{
$session = $this->manager->driver();
// 判断是否是接口访问并根据实际情况选择 SessionID 的获取方式
if ($request->headers->has('x-session-token')) {
$sessionId = $request->headers->has('x-session-token');
} else {
$sessionId = $request->cookies->get($session->getName());
}
$session->setId($sessionId);
return $session;
}

Aber es gab auch Probleme. . .

Schieben Sie es nach der Änderung in den Hauptentwicklungszweig. Leider wurde in diesem Fall ein Fehler gemeldet Die CSRF-Komponente hat einen Token-Fehler gemeldet. Das hier bereitgestellte Token unterscheidet sich nicht vom üblichen, und das Problem muss bei der Sitzung liegen.

Es ist erwähnenswert, dass ich sagen kann, dass das Ändern des Middleware-Codes überhaupt keine Auswirkungen auf das Framework hat. Tatsächlich ist dies nicht der Fall, da ich den von mir erstellten Middleware-Code geändert habe Geerbter Middleware-Code hilft auch nicht, aber seltsamerweise habe ich dieses Problem nicht, nachdem ich die Middleware wieder auf die ursprüngliche Middleware umgestellt habe.

Also habe ich den Code unter normalen und abnormalen Bedingungen ausgeführt, mit Haltepunkten an wichtigen Punkten debuggt und festgestellt, dass das Problem in einem wichtigen Attribut der Middleware liegt, $sessionHandled. Wenn der Wert falsch ist, dann Will Ursache unserer vorherigen Situation. Der Schlüssel ist, dass beim Starten der Middleware die Handle-Methode verwendet wird. Für die Session-Middleware lautet die erste Codezeile der Handle-Methode:

$this->sessionHandled = true;

Interessant. . .

Wir wissen es. Das Merkmal des Laravel-Frameworks ist sein IoC-Container, der für die Initialisierung verschiedener Klassen im Framework verantwortlich ist, um verschiedene Abhängigkeitsinjektionen zu implementieren, um eine lose Kopplung zwischen Komponenten sicherzustellen. Middleware ist sicherlich keine Ausnahme. Sie müssen wissen, dass der größte Unterschied zwischen einem Singleton und einer gewöhnlichen Instanz darin besteht, dass der Singleton immer gleich ist und die Eigenschaften in der Instanz nicht initialisiert werden Middleware muss ein Singleton sein, und die von mir selbst erstellte Middleware ist nur eine Instanz einer gewöhnlichen Klasse. Aber um zu wissen, was passiert und warum, muss ich meine Idee bestätigen (tatsächlich habe ich bereits über die Lösung nachgedacht, die später besprochen wird).

Dann liegt das Problem ungefähr in der Initialisierung der Middleware, also muss ich aufmuntern und mir den Startup-Code von Laravel genauer ansehen. Der entscheidende Punkt liegt hier in einer Klasse namens IlluminatePipelinePipeline.

Dieser Kurs verfügt über drei wichtige Methoden: senden, durch und dann. Wo ist dann der Schlüssel, mit dem alles beginnt? Bei dieser Klasse handelt es sich hauptsächlich um eine Sache, die kontinuierlich mehrere Framework-Startschritte ausführt. Der erste besteht darin, die für den Verarbeitungsprozess erforderlichen Komponenten (Anfrage und Middleware) zu initialisieren und zweitens die Anforderung durch den aus diesen Verarbeitungskomponenten bestehenden Stapel zu leiten Middleware und Routing-Dispatch-Komponenten) und gibt schließlich das Verarbeitungsergebnis (Response) zurück.

Man kann sagen, dass dieses Ding der Kern des Laravel-HTTP-Teils ist (naja, ursprünglich war es der Kernel). Dann liegt das vorherige Problem in der then-Methode von Pipeline und der von ihr aufgerufenen getSlice-Methode. Wenn Sie die getSlice-Methode direkt beobachten, können Sie feststellen, dass sie für die Generierung des Verarbeitungsstapels und die Instanziierung der Middleware-Klasse verantwortlich ist >

protected function getSlice()
{
return function ($stack, $pipe) {
return function ($passable) use ($stack, $pipe) {
if ($pipe instanceof Closure) {
return call_user_func($pipe, $passable, $stack);
} else {
list($name, $parameters) = $this->parsePipeString($pipe);
return call_user_func_array([$this->container->make($name), $this->method],
array_merge([$passable, $stack], $parameters));
}
};
};
}
Sie können $this->container->make($name) bemerken, was bedeutet, dass es eine Middleware-Klasse initialisiert, die einfach make ist, wenn es sich nicht um einen Singleton handelt, der wiederholt verwendet wird neu, was dazu führt, dass die vorherigen Eigenschaften initialisiert werden.


Dann liegt die Lösung auf der Hand: Machen Sie es zu einem Singleton.

Ich habe die folgende Codezeile in der Registermethode von app/Providers/AppServiceProvider.php hinzugefügt, die das vorherige Problem gelöst hat:

$this->app->singleton(SessionStart : :class); // SessionStart ist der Name meiner Middleware-Klasse

Das Obige führt Sie in die gesamte Analyse des Session-Schreibfehlerproblems ein, das durch die Erweiterung der Standard-Session-Middleware von Laravel verursacht wird.

Weitere verwandte Artikel zur Analyse des Session-Schreibfehlerproblems, das durch die Erweiterung der Standard-Session-Middleware von Laravel verursacht wird, finden Sie auf der chinesischen PHP-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