Signatur
Beschreibung
SessionUpdateTimestampHandlerInterface ist eine ergänzende Schnittstelle zu SessionHandlerInterface. Sie definiert zwei optionale Methoden, die es einem benutzerdefinierten Session-Handler ermöglichen, den Zeitstempel einer Session zu prüfen und zu aktualisieren, ohne die Session-Daten neu zu schreiben.
Diese Schnittstelle ist besonders nützlich, wenn Sessions auf der Serverseite mit einem eigenen Speicher-Backend (z. B. Redis, Datenbank) verwaltet werden und dabei eine effiziente Verlängerung der Session-Lebensdauer ohne unnötiges Schreiben der vollständigen Session-Daten gewünscht ist. PHP ruft intern validateId() auf, um zu prüfen, ob eine Session-ID gültig und aktuell ist, und updateTimestamp(), um den Zeitstempel zu aktualisieren ohne die Daten zu schreiben.
Ohne diese Schnittstelle würde PHP bei jedem Request die gesamten Session-Daten neu schreiben, was bei häufigen Anfragen oder großen Session-Daten zu erheblichem Overhead führen kann. Durch die Implementierung dieser Schnittstelle zusammen mit SessionHandlerInterface kann das Verhalten gezielt optimiert werden.
Ein eigener Session-Handler wird über session_set_save_handler() registriert und muss dabei sowohl SessionHandlerInterface als auch – für die Zeitstempel-Funktionalität – SessionUpdateTimestampHandlerInterface implementieren.
Beispiele
Benutzerdefinierter Session-Handler mit Zeitstempel-Unterstützung
<?php
class RedisSessionHandler implements SessionHandlerInterface, SessionUpdateTimestampHandlerInterface
{
private Redis $redis;
private int $ttl;
public function __construct(Redis $redis, int $ttl = 1800)
{
$this->redis = $redis;
$this->ttl = $ttl;
}
public function open(string $path, string $name): bool
{
return true;
}
public function close(): bool
{
return true;
}
public function read(string $id): string|false
{
return $this->redis->get('sess:' . $id) ?: '';
}
public function write(string $id, string $data): bool
{
return $this->redis->setex('sess:' . $id, $this->ttl, $data);
}
public function destroy(string $id): bool
{
$this->redis->del('sess:' . $id);
return true;
}
public function gc(int $max_lifetime): int|false
{
// Redis übernimmt das Ablaufen automatisch via TTL
return 0;
}
// --- SessionUpdateTimestampHandlerInterface ---
/**
* Prüft, ob eine Session-ID existiert und noch gültig ist.
*/
public function validateId(string $id): bool
{
return (bool) $this->redis->exists('sess:' . $id);
}
/**
* Verlängert die TTL der Session, ohne die Daten neu zu schreiben.
*/
public function updateTimestamp(string $id, string $data): bool
{
return (bool) $this->redis->expire('sess:' . $id, $this->ttl);
}
}
$redis = new Redis();
$redis->connect('127.0.0.1', 6379);
$handler = new RedisSessionHandler($redis, 3600);
session_set_save_handler($handler, true);
session_start();
$_SESSION['user'] = 'Max';
echo 'Session gestartet für: ' . $_SESSION['user'];
Einfache In-Memory-Implementierung zum Testen
<?php
class ArraySessionHandler implements SessionHandlerInterface, SessionUpdateTimestampHandlerInterface
{
private array $store = [];
private array $timestamps = [];
public function open(string $path, string $name): bool { return true; }
public function close(): bool { return true; }
public function read(string $id): string|false
{
return $this->store[$id] ?? '';
}
public function write(string $id, string $data): bool
{
$this->store[$id] = $data;
$this->timestamps[$id] = time();
return true;
}
public function destroy(string $id): bool
{
unset($this->store[$id], $this->timestamps[$id]);
return true;
}
public function gc(int $max_lifetime): int|false
{
$expired = 0;
$cutoff = time() - $max_lifetime;
foreach ($this->timestamps as $id => $ts) {
if ($ts < $cutoff) {
$this->destroy($id);
$expired++;
}
}
return $expired;
}
public function validateId(string $id): bool
{
return isset($this->store[$id]);
}
public function updateTimestamp(string $id, string $data): bool
{
if (isset($this->timestamps[$id])) {
$this->timestamps[$id] = time();
return true;
}
return false;
}
}
$handler = new ArraySessionHandler();
session_set_save_handler($handler, true);
session_start();
$_SESSION['test'] = 42;
echo 'Session-Wert: ' . $_SESSION['test'];
// Wichtig · Fallstricke
Sicherheitshinweis: Stellen Sie sicher, dass validateId() Session-IDs strikt validiert. Eine fehlerhafte Implementierung, die ungültige oder abgelaufene IDs akzeptiert, kann zu Session-Fixation- oder Replay-Angriffen führen.
Zusammenspiel mit session.lazy_write: Wenn die PHP-INI-Option session.lazy_write aktiviert ist (Standard seit PHP 7.0), ruft PHP updateTimestamp() auf, wenn sich die Session-Daten nicht geändert haben, anstatt write(). Dies reduziert unnötige Schreiboperationen erheblich.
Achtung: Diese Schnittstelle muss immer zusammen mit SessionHandlerInterface implementiert werden. Allein reicht sie nicht aus, um einen vollständigen Session-Handler bereitzustellen.