PHP / Session үндэс

Session үндэс

HTTP протокол нь stateless — сервер нэг хүсэлт ирэх бүрд хэрэглэгчийг "мартдаг". Нэвтэрсэн хэрэглэгч дараагийн хуудасруу орохоор сервер тэр хүнийг танидаггүй болно. Session нь яг энэ асуудлыг шийддэг: хэрэглэгчийн мэдээллийг серверт хадгалж, хуудсуудын хооронд "санаж" байдаг. Session-ийн ачаар нэвтрэлтийн систем, сагс, хэрэглэгчийн тохиргоо зэрэг боломжит болдог.

Session хэрхэн ажилладаг вэ?

Session эхлэхэд PHP дараах үйлдлүүдийг хийдэг:

код
1. Өвөрмөц session ID үүсгэнэ (жишээ: "abc123xyz...")
2. Тэр ID-г хэрэглэгчийн браузерт cookie болгон хадгална
3. Серверт тухайн ID-тэй холбоотой өгөгдлийн файл үүсгэнэ
4. Хэрэглэгч дараагийн хүсэлт илгээхэд cookie-г автоматаар дагуулж явуулна
5. PHP cookie-г уншиж, серверийн өгөгдлийг нэг дор буцаана
php
<?php
// session_start() нь АЛИВАА HTML-ийн ӨМНӨ дуудагдах ёстой
session_start();

// $_SESSION массив руу шууд бичнэ
$_SESSION['хэрэглэгч_нэр'] = 'Болд';
$_SESSION['хэрэглэгч_id']  = 42;
$_SESSION['нэвтэрсэн']     = true;
$_SESSION['нэвтэрсэн_цаг'] = time();

echo "Session ID: " . session_id() . "\n";
echo "Сайн уу, " . $_SESSION['хэрэглэгч_нэр'] . "!\n";
?>

session_start() нь хуудсын хамгийн эхэнд, ямар нэг гаралт хэвлэхээс өмнө дуудагдах ёстой — эсвэл "headers already sent" алдаа гарна.

Нэвтрэлтийн систем бүтээх

Session-ийн хамгийн нийтлэг хэрэглээ бол нэвтрэлт (login) систем. Дараах жишээнд энгийн нэвтрэлт хэрэгжүүлнэ:

php
<?php
// login.php
session_start();

// Аль хэдийн нэвтэрсэн бол нүүр хуудас руу илгээнэ
if (isset($_SESSION['нэвтэрсэн']) && $_SESSION['нэвтэрсэн'] === true) {
    header('Location: dashboard.php');
    exit;
}

$алдаа = '';

if ($_SERVER['REQUEST_METHOD'] === 'POST') {
    $имэйл    = trim($_POST['имэйл'] ?? '');
    $нууц_үг  = $_POST['нууц_үг'] ?? '';

    // Бодит програмд PDO-оор өгөгдлийн сангаас авна
    $хэрэглэгчид = [
        'bold@example.mn' => ['id' => 1, 'нэр' => 'Болд', 'нууц_үг' => password_hash('1234', PASSWORD_BCRYPT)],
    ];

    if (isset($хэрэглэгчид[$имэйл]) && password_verify($нууц_үг, $хэрэглэгчид[$имэйл]['нууц_үг'])) {
        // Нэвтрэлт амжилттай — session тохируулна
        session_regenerate_id(true); // Шинэ ID үүсгэнэ — session fixation халдлагаас хамгаалдаг
        $_SESSION['нэвтэрсэн']     = true;
        $_SESSION['хэрэглэгч_id']  = $хэрэглэгчид[$имэйл]['id'];
        $_SESSION['хэрэглэгч_нэр'] = $хэрэглэгчид[$имэйл]['нэр'];
        $_SESSION['нэвтэрсэн_цаг'] = time();

        header('Location: dashboard.php');
        exit;
    }

    $алдаа = "И-мэйл эсвэл нууц үг буруу байна.";
}
?>
<!DOCTYPE html>
<html>
<body>
<?php if ($алдаа): ?>
    <p><?= htmlspecialchars($алдаа) ?></p>
<?php endif; ?>
<form action="" method="post">
    <input type="email"    name="имэйл"   placeholder="И-мэйл">
    <input type="password" name="нууц_үг" placeholder="Нууц үг">
    <button type="submit">Нэвтрэх</button>
</form>
</body>
</html>

password_hash() нь нууц үгийг аюулгүй хэш болгоно. password_verify() нь хэш болон цэвэр нууц үгийг харьцуулна. Нууц үгийг хэзээ ч цэвэрээр хадгалж болохгүй.

Нэвтрэлт шалгах — хамгаалагдсан хуудас

Нэвтрэлт шаардсан хуудас бүрийн эхэнд session шалгана:

php
<?php
// dashboard.php
session_start();

// Нэвтрээгүй бол нэвтрэлтийн хуудас руу илгээнэ
function нэвтрэлт_шаардах(): void {
    if (!isset($_SESSION['нэвтэрсэн']) || $_SESSION['нэвтэрсэн'] !== true) {
        header('Location: login.php');
        exit;
    }

    // Session хугацаа хэтэрсэн эсэх шалгах (30 минут)
    $хугацаа = 30 * 60;
    if (time() - $_SESSION['нэвтэрсэн_цаг'] > $хугацаа) {
        session_destroy();
        header('Location: login.php?шалтгаан=хугацаа');
        exit;
    }

    // Идэвхтэй байх үед цагийг шинэчилнэ
    $_SESSION['нэвтэрсэн_цаг'] = time();
}

нэвтрэлт_шаардах(); // Хамгаалагдсан хуудас бүрийн эхэнд
?>

<!DOCTYPE html>
<html>
<body>
    <h1>Сайн уу, <?= htmlspecialchars($_SESSION['хэрэглэгч_нэр']) ?>!</h1>
    <a href="logout.php">Гарах</a>
</body>
</html>

Гарах — session устгах

php
<?php
// logout.php
session_start();

// Session-ийн бүх өгөгдлийг арилгана
$_SESSION = [];

// Cookie-г браузераас устгана
if (ini_get("session.use_cookies")) {
    $параметрүүд = session_get_cookie_params();
    setcookie(
        session_name(), '', time() - 42000,
        $параметрүүд["path"],   $параметрүүд["domain"],
        $параметрүүд["secure"], $параметрүүд["httponly"]
    );
}

// Серверийн session файлыг устгана
session_destroy();

header('Location: login.php');
exit;
?>

Session зөв устгахад гурван алхам хэрэгтэй: $_SESSION = [] өгөгдлийг арилгах, setcookie cookie-г устгах, session_destroy() серверийн файлыг устгах.

Flash мэдэгдэл — нэг удаагийн мэдэгдэл

Session ашиглан нэг л хуудсанд харагдаж устдаг "амжилттай", "алдаа" гэх мэт мэдэгдэл хэрэгжүүлж болно:

php
<?php
session_start();

// Flash мэдэгдэл тохируулах
function flash_тохируулах(string $төрөл, string $мэдэгдэл): void {
    $_SESSION['flash'] = ['төрөл' => $төрөл, 'мэдэгдэл' => $мэдэгдэл];
}

// Flash мэдэгдэл авч, устгах
function flash_авах(): ?array {
    if (!isset($_SESSION['flash'])) return null;
    $flash = $_SESSION['flash'];
    unset($_SESSION['flash']); // Нэг л удаа харагдаад устна
    return $flash;
}

// Тохируулах жишээ (хадгалсны дараа)
flash_тохируулах('амжилт', 'Хэрэглэгч амжилттай бүртгэгдлээ!');
header('Location: users.php');
exit;
?>

<?php
// users.php — дараагийн хуудсанд
session_start();
$мэдэгдэл = flash_авах();
?>
<?php if ($мэдэгдэл): ?>
    <div class="<?= $мэдэгдэл['төрөл'] ?>">
        <?= htmlspecialchars($мэдэгдэл['мэдэгдэл']) ?>
    </div>
<?php endif; ?>

Дараагийн хичээлд:

Cookie-ийн ажиллагааг судална. Session-оос ялгаатай нь cookie нь хэрэглэгчийн браузерт хадгалагддаг. setcookie(), expire огноо, secure тугуудыг хэрхэн тохируулдгийг жишээгээр үзнэ.