Der Fehler tritt auf, wenn das WBB oder eine andere WCF-Software mit einem Browser, der einen sehr langen UserAgent-String übermittelt, verwendet wird. Dabei wird bei jedem Request an den Server eine neue Session generiert, die Session kann nicht behalten werden und der Userlogin und verschiedene andere Funktionen, die ein funktionierendes Sessionsystem benötigen, können nicht richtig oder gar nicht verwendet werden. Zudem wird die Sessiontabelle in der Datenbank mit ungültigen Sessions gefüllt und der Besucherzähler wird bei jedem Refresh um Eins erhöht.
Problembeschreibung
Es geht um die validate() Methode in der Sessionklasse:
PHP:
// wcf/lib/system/session/Session.class.php (Zeile 252)
protected function validate() {
if ((SESSION_VALIDATE_USER_AGENT && $this->userAgent != UserUtil::getUserAgent())) {
return false;
}
[...]
}
Wie man sehen kann wird $this->userAgent mit UserUtil::getUserAgent() verglichen und wenn die beiden
nicht den gleichen String beinhalten, wird die Session als ungültig markiert.
Wenn wir jetzt mal in der UserUtil-Klasse nachschauen, was getUserAgent() liefert, sehen wir:
PHP:
// wcf/lib/util/UserUtil.class.php (Zeile 92)
public static function getUserAgent() {
if (isset($_SERVER['HTTP_USER_AGENT'])) return $_SERVER['HTTP_USER_AGENT'];
return '';
}
Das heißt also, getUserAgent liefert den
ungefilterten HTTP_USER_AGENT-String aus dem $_SERVER[]-Array, genau so wie er vom Browser geliefert wurde.
$this->userAgent liefert den userAgent=Wert, der für diese Session in der Datenbank gespeichert wurde. Kurzer Blick in die Datenbank:
SQL:
-- mysql.sql (Zeile 401)
CREATE TABLE wcf1_session (
[...]
userAgent varchar(255) NOT NULL default '',
[...]
) [...]
Oha! userAgent in der Datenbank speichert
maximal 255 Zeichen! Der Rest wird einfach abgeschnitten! Was aber wenn der Browser des Clients einen längeren String liefert? Ganz klar, die Sessionvalidierung schlägt jedes Mal fehl: Die validate() Methode vergleicht den ungefilterten String mit dem abgeschnittenen String, gibt false zurück, markiert die Session damit als ungültig und veranlasst somit die Generierung einer neuen Session.
Warum scheint der Bug ziemlich unbekannt zu sein und warum haben nur sehr wenige Nutzer Probleme? So gut wie alle aktuellen Browser liefern einen userAgent-String, der weit unter der Grenzlänge von 255 Zeichen ist.
Meine Tests ergaben folgendes:
Firefox 3.5.2 - 110 Zeichen
Chrome 3.0.195.6 - 116 Zeichen
Eine Ausnahme ist hier der Internet Explorer 8, welcher bei mir
298 Zeichen liefert. Auf einem anderen Rechner generierte der IE8 nur 210 Zeichen. Es scheint darauf anzukommen, welche und wie viele Versionen der Common Language Runtime des .NET Frameworks auf dem Rechner installiert sind. Diese (zusammen mit anderen Dingen wie OfficeLiveConnector etc.) werden mit in den UserAgent-String aufgenommen und an den Server gesendet.
So können leicht 300 Zeichen und mehr zusammenkommen. Möglicherweise könnte auch der Internet Explorer 7 einen zu langen UserAgent liefern, habe dazu momentan keine Testmöglichkeit.