Sessiya va cookie — $_SESSION, setcookie, oddiy login
Muammodan boshlaylik
Foydalanuvchi login sahifasida parolni to'g'ri kiritdi. Siz "Xush kelibsiz!" deb ko'rsatdingiz. U "Profil" havolasini bosdi — va server uni tanimaydi. Yana login so'raydi.
Sababi: HTTP xotirasiz (stateless) protokol. Har bir so'rov — butunlay yangi, mustaqil. Server oldingi so'rovni eslamaydi. Brauzer index.php ni so'radi, javob oldi — ish tugadi. Keyingi so'rov — begona odamdan kelgandek.
Foydalanuvchini sahifalar orasida "eslab qolish" uchun ikki vosita bor: cookie va sessiya.
Cookie — brauzerdagi kichik yozuv
Cookie — server brauzerga "buni saqlab qo'y va har safar menga qaytarib yubor" deb beradigan kichik matn.
<?php
// 30 kun saqlanadigan cookie
setcookie('til', 'uz', [
'expires' => time() + 60 * 60 * 24 * 30,
'path' => '/',
'httponly' => true,
'samesite' => 'Lax',
]);
Keyingi so'rovlarda brauzer uni avtomatik yuboradi:
<?php
$til = $_COOKIE['til'] ?? 'uz';
O'chirish — muddatini o'tmishga qo'yish:
<?php
setcookie('til', '', ['expires' => time() - 3600, 'path' => '/']);
[!WARNING]
setcookie()HTTP sarlavhasini yuboradi, shuning uchun u har qanday chiqishdan oldin chaqirilishi kerak —echodan, HTML dan, hatto<?phpdan oldingi bo'sh qatordan ham oldin. Aks holda:Warning: Cannot modify header information - headers already sent.
Cookie ning muammosi: u foydalanuvchining brauzerida turadi va uni foydalanuvchi o'zgartira oladi. $_COOKIE['admin'] = 'ha' deb saqlasangiz — har kim DevTools da o'zini admin qilib qo'yadi. Cookie ga faqat ahamiyatsiz narsalarni (til, mavzu) saqlang.
Sessiya — serverdagi xotira
Sessiya ma'lumotni serverda saqlaydi. Brauzerga faqat tasodifiy ID (kalit) beriladi.
Hayotiy o'xshatma: garderob. Paltongizni topshirasiz (ma'lumot serverda qoladi), qo'lingizga raqamli bilet berishadi (sessiya ID cookie da). Bilet bo'yicha paltongizni qaytarishadi. Biletda paltoning o'zi yo'q, va boshqa raqamni taxmin qilish deyarli imkonsiz.
<?php
session_start(); // har bir sahifaning boshida, har qanday chiqishdan oldin
$_SESSION['foydalanuvchi_id'] = 42;
$_SESSION['ism'] = 'Shahnoza';
Boshqa sahifada:
<?php
session_start();
echo $_SESSION['ism'] ?? 'Mehmon'; // Shahnoza
session_start() qiladigan ish:
- Brauzerdan
PHPSESSIDcookie kelganmi? — keldi bo'lsa, shu ID dagi ma'lumotni yuklaydi - Kelmagan bo'lsa — yangi tasodifiy ID yaratadi va cookie sifatida yuboradi
- Sahifa tugaganda
$_SESSIONdagi o'zgarishlarni serverga saqlaydi
Cookie va sessiya farqi
| Cookie | Sessiya | |
|---|---|---|
| Ma'lumot qayerda | Brauzerda | Serverda |
| Foydalanuvchi o'zgartira oladimi | Ha | Yo'q (faqat ID ni ko'radi) |
| Hajm | ~4 KB | Cheklanmagan (amalda) |
| Muddat | Siz belgilaysiz | Brauzer yopilguncha (odatda) |
| Nima uchun | Til, mavzu, "meni eslab qol" | Login, savat, xabarlar |
Oddiy login tizimi
Hozircha parolni kod ichida saqlaymiz — 38-darsda bazaga va xeshlashga o'tamiz.
kirish.php:
<?php
declare(strict_types=1);
session_start();
// Vaqtinchalik "baza"
$foydalanuvchilar = [
'ali@mail.uz' => ['id' => 1, 'ism' => 'Ali', 'parol_hash' => password_hash('maxfiy123', PASSWORD_DEFAULT)],
];
$xato = '';
if ($_SERVER['REQUEST_METHOD'] === 'POST') {
$email = trim($_POST['email'] ?? '');
$parol = $_POST['parol'] ?? '';
$user = $foydalanuvchilar[$email] ?? null;
if ($user && password_verify($parol, $user['parol_hash'])) {
session_regenerate_id(true); // muhim! pastda tushuntirilgan
$_SESSION['user_id'] = $user['id'];
$_SESSION['ism'] = $user['ism'];
header('Location: profil.php');
exit;
}
$xato = "Email yoki parol noto'g'ri";
}
?>
<form method="post">
<?php if ($xato): ?><p style="color:red"><?= htmlspecialchars($xato) ?></p><?php endif; ?>
<input name="email" type="email" placeholder="Email">
<input name="parol" type="password" placeholder="Parol">
<button>Kirish</button>
</form>
profil.php — faqat kirganlar uchun:
<?php
declare(strict_types=1);
session_start();
if (!isset($_SESSION['user_id'])) {
header('Location: kirish.php');
exit;
}
?>
<h1>Salom, <?= htmlspecialchars($_SESSION['ism']) ?>!</h1>
<a href="chiqish.php">Chiqish</a>
chiqish.php:
<?php
session_start();
$_SESSION = []; // ma'lumotlarni tozalash
session_destroy(); // serverdagi sessiyani o'chirish
header('Location: kirish.php');
exit;
Nima uchun session_regenerate_id(true)?
Bu session fixation hujumidan himoya. Hujumchi o'ziga ma'lum bo'lgan sessiya ID ni qurbonning brauzeriga joylashtiradi (masalan, havola orqali). Qurbon shu ID bilan login qiladi. Endi hujumchi ham shu ID ni biladi — va qurbonning akkauntiga kiradi.
session_regenerate_id(true) login paytida ID ni yangisiga almashtiradi. Hujumchining bilgan eski ID si yaroqsiz bo'ladi.
Qoida: foydalanuvchi huquqi o'zgarganda (login, logout, rolni oshirish) — ID ni yangilang.
Flash xabarlar
"Profil saqlandi" kabi xabarni redirect dan keyin bir marta ko'rsatish:
<?php
// Saqlagandan keyin:
$_SESSION['flash'] = "Profil muvaffaqiyatli saqlandi";
header('Location: profil.php');
exit;
<?php
// profil.php da:
if (isset($_SESSION['flash'])) {
echo '<div class="xabar">' . htmlspecialchars($_SESSION['flash']) . '</div>';
unset($_SESSION['flash']); // ko'rsatdik — o'chiramiz
}
Xavfsiz sessiya sozlamalari
session_start() dan oldin yoki php.ini da:
<?php
session_set_cookie_params([
'httponly' => true, // JavaScript document.cookie orqali o'qiy olmaydi — XSS da o'g'irlanmaydi
'secure' => true, // faqat HTTPS orqali yuboriladi
'samesite' => 'Lax', // boshqa saytlardan kelgan so'rovlarda yuborilmaydi — CSRF dan qisman himoya
]);
session_start();
[!INFO]
secure => truemahalliyhttp://localhostda cookie yuborilmasligiga olib keladi. Ishlab chiqishdafalse, serverda (HTTPS)trueqiling.
Nima uchun shunday?
Nima uchun HTTP xotirasiz qilib yaratilgan? Eslab qolsa oson bo'lmasmidi?
1990-yillarda veb hujjatlarni ulashish uchun yaratilgan: so'radingiz — hujjatni oldingiz. Xotirasizlik serverni juda oddiy va kengaytiriladigan qiladi: har qanday so'rovni har qanday server bajara oladi, chunki hech kim oldingi holatni saqlab turmaydi. Internet do'konlar paydo bo'lganda "savat" kerak bo'ldi — va 1994-yilda Netscape cookie ni o'ylab topdi. Sessiyalar esa cookie ustiga qurilgan xavfsizroq qavat.
Tez-tez uchraydigan xatolar
session_start() ni unutish — $_SESSION bo'sh massivdek ishlaydi, hech narsa saqlanmaydi.
session_start() dan oldin chiqish:
Warning: session_start(): Session cannot be started after headers have already been sent
Fayl boshidagi bo'sh qator yoki BOM belgisi ham "chiqish" hisoblanadi.
header('Location: ...') dan keyin exit ni unutish — redirect sarlavhasi yuboriladi, lekin PHP pastdagi kodni baribir bajaradi. Himoyalangan sahifaning mazmuni javobga tushib qolishi mumkin.
Xulosa
Eslab qoling:
- HTTP xotirasiz — har bir so'rov mustaqil
- Cookie — brauzerda, foydalanuvchi o'zgartira oladi; muhim narsa saqlamang
- Sessiya — serverda; brauzerda faqat ID
session_start()— har bir sahifa boshida, chiqishdan oldin- Login da
session_regenerate_id(true), logout dasession_destroy() header('Location: ...')dan keyin doimexithttponly,secure,samesite— xavfsiz cookie sozlamalari
Keyingi dars
22-dars: Fayl yuklash — $_FILES, move_uploaded_file, xavfsizlik