Dennis: Session wenn kein Cookie, dann auch keine Session

Beitrag lesen

Hi Mike,

unset($_COOKIE);

$_COOKIE ist eine superglobale Variable, solche solltest du nie per unset() gänzlich löschen, da diese dann für alle Teile deines Scriptes nicht mehr zur Verfügung steht, was zu unerwarteten Problemen führen kann.

Aus diesem Grund solltest du, wenn du alle Daten aus $_COOKIE, $_SESSION etc. löschen willst nie unset() verwenden, sondern die Variable als leeres Array definieren:

$_COOKIES = array()

Beachte aber bitte, dass du hierdurch nur die Variablen in PHP löschst, welche für die vom Browser gesendeten Cookies stehen, keinesfalls aber die Cookies selber löschst. Den Browser anzuweisen ein Cookie zu löschen kannst du auscchließlich mit setcookie().

Warum wird session_start() trotzdem ausgeführt?

Das kann ich dir leider auch nicht sagen, ich habe versucht dein Problem an folgendem Code nachzuvollziehen:

~~~php var_dump($_COOKIE);
  unset($_COOKIE);
  var_dump($_COOKIE);
  if ($_COOKIE) {
    echo 'wahr';
  } else {
    echo 'falsch';
  }

  
Mit PHP 5.2.6 erhalte ich da folgende Ausgabe:  
  
  array(0) {  
  }  
  Notice: Undefined variable: \_COOKIE in /home/driehle/test.php on line 3  
  NULL  
  Notice: Undefined variable: \_COOKIE in /home/driehle/test.php on line 4  
  falsch  
  
Alles so, wie ich es erwartet hätte, dein Problem kann ich also nicht nachvollziehen. Vermutlich ist dein Original-Code länger und du hast vielleicht irgendeine wichtige Stelle fürs Posting hier herausgestrichen?  
  
  

> Ich habe da mal eine Vermutung. Kann es sein, weil ja dieser Cookie durch die Sessionprozedur von PHP gesetzt wurde, eben genau mit diesem Parameter gesetzt wurde und auch deshalb nur damit zu entfernen ist?  
  
Richtig, genau so ist es. Mit welchen Optionen session\_start() das Session-Cookie setzt kannst du aber über einige INI-Optionen beeinflussen. In deinem Fall kommt [session.cookie_path](http://de.php.net/manual/en/session.configuration.php#ini.session.cookie-path) zum Tragen, an der verlinkten Stelle im Handbuch steht auch, dass der Wert '/' der Default ist. (Was notwendig ist, weil dir das Session-Cookie sonst nicht für alle PHP-Scripte unter der verwendeten Domain zur Verfügung stände.)  
  
Wenn du das Session-Cookie bei jeder möglichen PHP-Konfiguration zuverlässig löschen willst, könntest du folgendes probieren:  
  
  ~~~php
setcookie(  
     session_name(),  
     '',  
     time() - 3600,  
     ini_get('session.cookie_path'),  
     ini_get('session.cookie_domain'),  
     ini_get('session.cookie_secure'),  
     ini_get('session.cookie_httponly')  
   );

Alternativ kannst du vor dem Starten der Session natürlich auch die Optionen für das Session-Cookie per ini_set() oder per session_set_cookie_params() explizit setzen, dann brauchst du sie beim Löschen des Cookies nicht mehr aus der PHP-Konfiguration abzurufen.

Wenn dem so ist, ist das ganz schön doof. Denn die Sessionfunktionen setzen zwar einen Cookie beim User, aber eine Funktion zum Enfernen haben sie nicht, richtig?

Anders gefragt: Warum willst du das Session-Cookie überhaupt löschen? Standardmäßig hat ein Session-Cookie eine Lifetime von 0, was bedeutet, dass der Browser das Cookie löscht, sobald er beendet wird. Startet der Besucher also seinen Browser neu, ist das Cookie eh weg.

Wenn du möchtest, dass der User seine Rechte verliert, welche er eventuell besitzt, weil er sich gerade eingeloggt hat, so ist der gängige Weg, dass du nicht das Cookie beim Client löschst, sondern per

$_SESSION = array();

die Daten bei dir auf dem Server. Dann kann kommen was oder wer(!) will, die Session-ID „gibt es zwar noch” (und zwar in der Form, dass der Server noch eine entsprechende Datei irgendwo abgelegt hat), die Session selber, also die Daten der Session gibts aber nicht mehr. Und somit ist diese nun leere Session gleichbedeutend mit einer nicht existenten Session.

Schön wäre also wenn session_destroy() das direkt mit übernehmen würde, aber so was gibt es nicht, oder?

session_destroy() würde ich gar nicht benutzen, weil es nicht viel bringt. Wie du die Daten einer Session gelöscht kriegst habe ich dir oben schon gezeigt. Was macht session_destroy() mehr? Es löscht noch die Session-Datei auf dem Server (das was du in deinem tmp Ordner siehst), aber das bringt dir nichts, weil du dich nicht darauf verlassen kannst, dass der Besucher sich auch wirklich ausloggt, sprich du hast keine Garantie, dass session_destroy() auch wirklich für jeder erzeugte Session am Ende auch wieder aufgerufen wird. Wenn der Besucher also einfach seinen Browser zu macht hast du in jedem Fall so oder so eine verwaiste Session-Datei auf dem Server.

Was ich sagen will: Alte (verwaiste) Session-Dateien zu löschen ist aus meiner Sicht nicht deine Aufgabe als PHP-Programmierer, sondern eine Aufgabe von PHP mit seinem Session Garbage Collector oder Aufgabe des Betriebssystem durch z.B. einen Cronjob (so macht es Debian).

Zu deinem hier beschriebenen Problem hat dir Tom ja bereits geschrieben - in deinem PHP-Script löschst du stets zuerst alle Cookies, folglich auch das Session-Cookie, da dieses auch nichts anderes als ein normales Cookie ist.

Infolge des fehlenden Session-Cookies startet PHP nunmal bei jedem Seitenaufruf eine neue PHP-Session und folglich kriegst du für jeden Seitenaufruf eine neue Session-Datei in deinem tmp Ordner (diesen kannst du übrigens über session.save_path festlegen).

Irgendwann werden diese Session-Dateien im tmp Ordner auch wieder gelöscht, allerdings frühestens, nachdem sie ihre maximale Lebenszeit erreicht haben. Das sind in der Standardeinstellung 1440 Sekunden, also 24 Minuten - dann erst könnten die Session-Dateien gelöscht werden.

Aber: Das Aufräumen des tmp Ordners ist eine relativ aufwendige Aktione, da PHP hierfür alle Dateien angucken muss, schauen muss wann diese erstellt wurden, ob dies bereits länger als 24 Minuten her ist und wenn ja, diese dann zu löschen. Aus diesem Grund führt räumt PHP nicht bei jedem Seitenaufruf den tmp Ordner auf, sondern nur bei ca. 1% aller Seitenaufrufe. Das lässt sich über session.gc_probability und session.gc_divisor regeln. In der Standardkonfiguration löst also im Mittel nur jeder 100. Seitenaufruf eine Aufräumen des tmp Ordners aus, und auch dann werden natürlich nur die Dateien gelöscht, welche älter als session.gc_maxlifetime Sekunden alt sind.

Insofern: Dass sich im tmp Ordner erst mal Dateien ansammeln ist durchaus normal.

Viele Grüße,
  ~ Dennis.