Kodokon kodokon.com

Сессии и куки: вход и корзина

Запоминай посетителей от страницы к странице: безопасный вход, корзина в сессии и правильно защищённые куки.

10 мин · 3 вопросов

Открыть этот урок в Kodokon

HTTP ничего не помнит: каждый запрос приходит как новый, без связи с предыдущим. Сессии решают эту проблему: session_start() связывает посетителя с уникальным идентификатором, который передаётся в куке, и с хранилищем на стороне сервера, доступным через $_SESSION. Вызывай session_start() в самом начале каждой нужной страницы, до любого вывода.

PHP
<?php

declare(strict_types=1);

session_start();

$storedHash = password_hash('secret123', PASSWORD_DEFAULT);
$password = $_POST['password'] ?? '';

if (password_verify($password, $storedHash)) {
    session_regenerate_id(true);
    $_SESSION['user_id'] = 42;
    header('Location: /account.php');
    exit;
}

echo "Invalid credentials.";
login.php: в реальности хеш берётся из твоей базы данных.

Защита страницы сводится к проверке того, что пользователь есть в сессии, и к редиректу в противном случае. Сессия также идеально подходит как временное хранилище для корзины: ассоциативный массив id товара => количество переживает переходы между страницами.

PHP
<?php

declare(strict_types=1);

session_start();

if (!isset($_SESSION['user_id'])) {
    header('Location: /login.php');
    exit;
}

$_SESSION['cart'] ??= [];

$productId = filter_input(
    INPUT_POST,
    'product_id',
    FILTER_VALIDATE_INT
);

if (is_int($productId)) {
    $qty = $_SESSION['cart'][$productId] ?? 0;
    $_SESSION['cart'][$productId] = $qty + 1;
}

$count = array_sum($_SESSION['cart']);
echo "Cart: " . $count . " item(s)";
cart.php: защищённая страница и корзина, сохранённая в сессии.

Куки, наоборот, живут на устройстве пользователя и переживают закрытие браузера: отлично подходят для темы оформления или выбранного языка. Начиная с PHP 7.3 setcookie() принимает массив опций: требуй secure (только по HTTPS), httponly (невидим для JavaScript) и samesite (ограничивает отправку с других сайтов).

PHP
<?php

setcookie('theme', 'dark', [
    'expires' => time() + 60 * 60 * 24 * 30,
    'path' => '/',
    'secure' => true,
    'httponly' => true,
    'samesite' => 'Lax',
]);

$theme = $_COOKIE['theme'] ?? 'light';
echo "Active theme: " . $theme;
Кука с настройкой на тридцать дней и с правильными флагами.

Выход должен быть проработан так же тщательно, как вход: очисти $_SESSION, уничтожь сессию на стороне сервера и просрочь куку, которая несла идентификатор.

PHP
<?php

session_start();

$_SESSION = [];
session_destroy();

setcookie(session_name(), '', time() - 3600, '/');

header('Location: /login.php');
exit;
logout.php: полный выход, не оставляющий следов.

Проверка знаний

Убедись, что запомнил ключевые моменты этого урока.

  1. Где хранятся данные PHP-сессии?
    • В куке на устройстве пользователя
    • На сервере; браузер хранит в куке только идентификатор
    • В URL каждой страницы
    • В localStorage браузера
  2. Зачем вызывать session_regenerate_id(true) сразу после успешного входа?
    • Чтобы предотвратить фиксацию сессии: идентификатор, известный до входа, становится непригодным
    • Чтобы продлить время жизни куки сессии
    • Чтобы очистить старые данные корзины
  3. Что делает опция httponly у куки?
    • Она шифрует содержимое куки
    • Она ограничивает куку незащищёнными соединениями
    • Она делает куку недоступной для JavaScript на странице, что ограничивает кражу через XSS