Poznajemy w bardzo szczegółowy sposób zagadnienia związane z sesją, jej przechowywaniem i obsługą w języku PHP. Do dzieła.
Sprawdzanie statusu sesji (i warunkowe jej uruchamianie):
public static function start()
{
if (session_status() == PHP_SESSION_NONE) {
session_start();
}
}
Zapisywanie do sesji:
public static function set($key, $value)
{
$_SESSION[$key] = $value;
}
Odczyt z sesji:
public static function get($key, $default = null)
{
return isset($_SESSION[$key]) ? $_SESSION[$key] : $default;
}
Sprawdzanie istnienia danych w sesji:
public static function has($key)
{
return isset($_SESSION[$key]);
}
Oczyszczenie zmiennej w sesji:
public static function clear($key)
{
if (isset($_SESSION[$key])) {
unset($_SESSION[$key]);
}
}
Usunięcie zmiennych sesyjnych oraz samej sesji:
public static function clearAll()
{
//zmienne:
session_unset();
//sesja:
session_destroy();
//cookie nadal w twojej przeglądarce btw
}
Prawidłowe usunięcie zmiennych sesyjnych, sesji oraz cookie sesyjnego po stronie klienta:
public function logout()
{
// unset($_SESSION['user']);
session_destroy();
// session_regenerate_id();
$params = session_get_cookie_params();
setcookie(
'PHPSESSID',
'',
time() - 3600,
$params['path'],
$params['domain'],
$params['secure'],
$params['httponly']
);
}
Usunięcie poprzez ustawienie pustego sessid oraz aktualizację pliku cookie o czas wygaśnięcia będący czasem przeszłym – backend nie może w przeglądarce tak sobie rzeczy usuwać.
Dalej, regeneracja (ponowne stworzenie) session_id dla utrudnienia hakerom roboty przy zachowaniu sesji oraz jej zmiennych i cookie (np. po zalogowaniu):
public function login(array $formData)
{
//(...)
if (!$user || !$passwordsMatch) {
throw new ValidationException(['password' => ['Invalid credentials']]);
}
session_regenerate_id();
$_SESSION['user'] = $user['id'];
}
Wywalenie błędu jeżeli sesja już istnieje (customowy error):
if (session_status() === PHP_SESSION_ACTIVE) {
throw new SessionException("Session already active.");
}
Wywalenie błędu jeżeli nagłówki zostały przedwcześnie wysłane (ktoś zapomniał włączyć output buffering):
if (headers_sent($filename, $line)) {
throw new SessionException("Headers already sent. Consider enabling output buffering. Data outputted from {$filename} - Line: {$line}");
}
Ustawienie bezpieczeństwa względnie rygorystyczne, ale luzujące SSL ja deweloperce:
session_set_cookie_params([
'secure' => $_ENV['APP_ENV'] === "production",
'httponly' => true,
'samesite' => 'lax'
]);
Cały middleware zajmujący się stworzeniem sesji:
class SessionMiddleware implements MiddlewareInterface
{
public function process(callable $next)
{
if (session_status() === PHP_SESSION_ACTIVE) {
throw new SessionException("Session already active.");
}
if (headers_sent($filename, $line)) {
throw new SessionException("Headers already sent. Consider enabling output buffering. Data outputted from {$filename} - Line: {$line}");
}
session_set_cookie_params([
'secure' => $_ENV['APP_ENV'] === "production",
'httponly' => true,
'samesite' => 'lax'
]);
session_start();
$next();
session_write_close();
}
}
Funkcja pokazująca gdzie zapisywane są pliki sesyjne oraz metoda licząca te pliki:
public static function sessionsCount(){
$session_path = session_save_path();
$handle = opendir($session_path);
$sessions = 0;
while (($file = readdir($handle)) != FALSE) {
if(in_array($file, ['.', '..']))
continue;
if(!preg_match("/^sess/", $file))
continue;
$sessions++;
}
return $sessions;
}