Session — express-session, cookie-session

~15 daq · Express · Autentifikatsiya va Xavfsizlik

Session nima?

HTTP — "stateless" protokol. Har so'rov mustaqil — server oldingi so'rovni eslamaydi. Foydalanuvchi login qildi, keyingi so'rovda server uni tanımaydi.

Session — serverning foydalanuvchini "eslab qolish" usuli. Login qilganda server session yaratadi, unga ID beradi. ID ni cookie ga saqlaydi. Keyingi so'rovlarda cookie yuboriladi, server session ni topadi.

JWT bilan farqi: JWT da server hech narsa saqlamaydi — ma'lumot tokenning o'zida. Session da esa server ma'lumotni saqlaydi, foydalanuvchiga faqat ID beriladi.

JWT:     [foydalanuvchi ma'lumoti token ichida] → server tekshiradi
Session: [faqat ID cookie da] → server ID bo'yicha ma'lumotni topadi

express-session

npm install express-session
const session = require('express-session');

app.use(session({
  secret:            process.env.SESSION_SECRET, // cookie ni imzolash uchun
  resave:            false,   // o'zgarmagan session ni qayta saqlamaslik
  saveUninitialized: false,   // bo'sh session ni saqlamaslik
  cookie: {
    maxAge:   24 * 60 * 60 * 1000, // 1 kun (millisekund)
    httpOnly: true,   // JavaScript o'qiy olmaydi — XSS dan himoya
    secure:   process.env.NODE_ENV === 'production', // faqat HTTPS
  },
}));

secret — cookie ni imzolash uchun maxfiy kalit. Kimdir cookie ni o'zgartirishga urinsa — imzo mos kelmaydi, server rad etadi.

httpOnly: true — muhim xavfsizlik sozlamasi. JavaScript document.cookie orqali session cookie ni o'qiy olmaydi. XSS hujumidan himoya.

secure: true — cookie faqat HTTPS orqali yuboriladi. Production da har doim.


Session bilan login

router.post('/login', async (req, res, next) => {
  try {
    const { email, password } = req.body;

    const result = await pool.query('SELECT * FROM users WHERE email = $1', [email]);
    const user   = result.rows[0];

    if (!user || !(await bcrypt.compare(password, user.password_hash))) {
      return res.status(401).json({ message: 'Email yoki parol noto\'g\'ri' });
    }

    // Session ga foydalanuvchi ma'lumotini saqlash
    req.session.userId = user.id;
    req.session.role   = user.role;

    res.json({ message: 'Kirish muvaffaqiyatli' });
  } catch (err) {
    next(err);
  }
});

// Session tekshiruvchi middleware
function requireAuth(req, res, next) {
  if (!req.session.userId) {
    return res.status(401).json({ message: 'Login kerak' });
  }
  next();
}

// Himoyalangan route
router.get('/profile', requireAuth, async (req, res, next) => {
  try {
    const result = await pool.query(
      'SELECT id, name, email FROM users WHERE id = $1',
      [req.session.userId]
    );
    res.json(result.rows[0]);
  } catch (err) {
    next(err);
  }
});

// Logout
router.post('/logout', (req, res) => {
  req.session.destroy((err) => {
    if (err) return res.status(500).json({ message: 'Xato' });
    res.clearCookie('connect.sid'); // session cookie ni o'chirish
    res.json({ message: 'Chiqish muvaffaqiyatli' });
  });
});

Session saqlash — qayerda?

Standart bo'yicha session xotirada saqlanadi. Bu development uchun yaxshi, lekin production da muammo:

  • Server qayta ishga tushsa — barcha session lar yo'qoladi
  • Bir nechta server bo'lsa — har biri o'z session larini bilmaydi

Production da session tashqi omborga saqlanadi — Redis eng mashhur tanlov:

npm install connect-redis
const RedisStore = require('connect-redis').default;
const redis      = require('./redis');

app.use(session({
  store:  new RedisStore({ client: redis }),
  secret: process.env.SESSION_SECRET,
  resave: false,
  saveUninitialized: false,
  cookie: { maxAge: 24 * 60 * 60 * 1000, httpOnly: true, secure: true },
}));

Endi session lar Redis da — server qayta ishga tushsa ham, bir nechta server bo'lsa ham — hammasi bir xil session larni ko'radi.


Session vs JWT — qachon qaysi?

Bu savol ko'p muhokama qilinadi. Qisqacha:

Session — an'anaviy web ilovalar uchun. Server session ni boshqaradi, logout darhol ishlaydi (session o'chiriladi). Lekin bir nechta server bo'lsa — tashqi saqlash kerak.

JWT — API lar, mobil ilovalar, microservices uchun. Server hech narsa saqlamaydi — masshtablash oson. Lekin logout qiyin — token muddati o'tguncha amal qiladi.

Web ilova (server-side render) → Session
REST API, mobil ilova          → JWT

Tez-tez uchraydigan xatolar

secret ni kod ichiga yozish:

// Xato:
app.use(session({ secret: 'mysecret' }));

// To'g'ri:
app.use(session({ secret: process.env.SESSION_SECRET }));

Production da secure: true unutish:

secure: true bo'lmasa — cookie HTTP orqali ham yuboriladi. Odam-o'rtada hujumida ushlab olinishi mumkin.

Xotirada session saqlash (production da):

// Xato — production da:
app.use(session({ /* store yo'q */ }));
// Server qayta ishga tushsa — barcha foydalanuvchilar qayta login qilishi kerak

Xulosa

Session — server foydalanuvchini eslab qoladi. ID cookie da, ma'lumot serverda. httpOnly va secure — muhim xavfsizlik sozlamalari.

Production da session Redis da saqlanadi — bir nechta server va qayta ishga tushishda muammo bo'lmaydi.

JWT — server hech narsa saqlamaydi, masshtablash oson. Session — logout darhol ishlaydi, an'anaviy web uchun.


Keyingi dars

25-dars: Cookie — cookie-parser, httpOnly, secure, sameSite