Các phương pháp xác thực & bảo mật ứng dụng-P4:Session-based Authentication

8 phút đọc

📌 1. Tổng quan — Session-based Auth là gì?

Hãy tưởng tượng bạn vào một khách sạn:

  • Bạn ra lễ tân, đưa CMND để xác minh danh tính (đăng nhập).
  • Lễ tân ghi tên bạn vào sổ và đưa cho bạn chìa khóa phòng (Session ID).
  • Mỗi lần bạn muốn vào phòng, bạn chỉ cần dùng chìa khóa đó — không cần xuất trình CMND lại.
  • Khi bạn trả phòng (đăng xuất), chìa khóa bị hủy và xóa khỏi sổ lễ tân.

Session-based Authentication hoạt động đúng như vậy — nhưng thay vì khách sạn, đó là web server của bạn.


🧱 2. Các khái niệm cốt lõi

Khái niệm Định nghĩa đơn giản Ví dụ thực tế
Session (Phiên làm việc) Bản ghi trên server lưu thông tin người dùng đang đăng nhập Trang sổ trong sổ lễ tân khách sạn
Session ID Một chuỗi ký tự ngẫu nhiên, duy nhất đại diện cho phiên đó Số phòng khách sạn / chìa khóa phòng
Cookie Nơi trình duyệt lưu Session ID và tự động gửi lên server mỗi request Cái ví của bạn — luôn mang theo chìa khóa
Session Store Nơi server lưu trữ toàn bộ session đang hoạt động (RAM, Redis, DB…) Bảng theo dõi tất cả khách đang ở trong khách sạn

⚙️ 3. Cơ chế hoạt động — Step by Step

Bước 1: Đăng nhập (Login)

Người dùng  →  Gửi username + password  →  Server
                                              ↓
                                    Kiểm tra thông tin
                                              ↓
                              Tạo Session trong Session Store
                              { sessionId: "abc123", userId: 42, expiry: ... }
                                              ↓
            Server  →  Gửi Cookie "sessionId=abc123"  →  Trình duyệt lưu lại

Bước 2: Mỗi request tiếp theo

Người dùng click "Xem đơn hàng"  →  Trình duyệt TỰ ĐỘNG gửi Cookie sessionId=abc123
                                                              ↓
                                                 Server tra cứu trong Session Store
                                                              ↓
                                              Tìm thấy → Trả về dữ liệu đơn hàng ✅
                                              Không tìm thấy → Redirect về /login ❌

Bước 3: Đăng xuất (Logout)

Người dùng nhấn Logout  →  Server xóa session khỏi Session Store
                        →  Trình duyệt xóa Cookie
                        →  sessionId=abc123 không còn hợp lệ nữa

🔄 4. Flow diagram đầy đủ

sequenceDiagram
    participant Browser as 🌐 Trình duyệt
    participant Server as 🖥️ Server
    participant Store as 🗄️ Session Store

    Browser->>Server: POST /login (username, password)
    Server->>Server: Xác minh thông tin
    alt ✅ Đăng nhập thành công
        Server->>Store: Tạo session (sessionId, userId, expiry)
        Store-->>Server: OK
        Server-->>Browser: 200 OK + Set-Cookie: sessionId=abc123
    else ❌ Sai thông tin
        Server-->>Browser: 401 Unauthorized
    end

    Note over Browser,Store: Người dùng tiếp tục sử dụng app...

    Browser->>Server: GET /orders (Cookie: sessionId=abc123)
    Server->>Store: Tra cứu sessionId=abc123
    alt ✅ Session hợp lệ
        Store-->>Server: userId=42, role=user
        Server-->>Browser: 200 OK + Dữ liệu đơn hàng
    else ⌛ Session hết hạn
        Server-->>Browser: 302 Redirect → /login
    end

    Browser->>Server: POST /logout
    Server->>Store: Xóa session abc123
    Server-->>Browser: 200 OK + Xóa Cookie

✅ 5. Ưu điểm

  • Kiểm soát tức thời: Server có thể vô hiệu hóa session ngay lập tức (khi đổi mật khẩu, phát hiện bất thường, bị hack).
  • Dễ triển khai: Hầu hết web framework đều hỗ trợ sẵn (Laravel, Django, Rails, Express…).
  • Phù hợp web truyền thống: Ứng dụng web có server-side rendering, người dùng dùng trình duyệt.
  • Dữ liệu session linh hoạt: Có thể lưu nhiều thông tin trong session (role, permissions, cart items…).

❌ 6. Nhược điểm & Hạn chế

  • Khó scale ngang (horizontal scaling): Nếu bạn có 3 server, session tạo ở server A sẽ không tồn tại ở server B → cần dùng Sticky Session hoặc Session Store tập trung (Redis).
  • Tốn tài nguyên server: Mỗi user đăng nhập = 1 bản ghi trong bộ nhớ/DB.
  • Không phù hợp cho API/Mobile: Mobile app không dùng Cookie theo cách trình duyệt làm — thường phải dùng JWT hoặc Token thay thế.
  • CSRF Risk: Vì Cookie được gửi tự động, cần phòng chống tấn công Cross-Site Request Forgery.

🔐 7. Bảo mật — Những điều BẮT BUỘC phải làm

Biện pháp Mục đích Cách làm
Cookie HttpOnly Ngăn JavaScript đọc cookie → chống XSS Set-Cookie: sessionId=...; HttpOnly
Cookie Secure Chỉ gửi qua HTTPS → chống nghe lén Set-Cookie: sessionId=...; Secure
Cookie SameSite Ngăn gửi cookie cross-site → chống CSRF Set-Cookie: sessionId=...; SameSite=Strict
Session Expiry Tự động hết hạn nếu không hoạt động Set TTL 30 phút, 1 giờ… tùy use case
Session Invalidation Hủy session khi đổi mật khẩu/phát hiện bất thường Xóa session khỏi store khi user đổi pass
Session Regeneration Tạo Session ID mới sau khi đăng nhập thành công Tránh Session Fixation Attack

⚖️ 8. So sánh với JWT (Token-based)

Tiêu chí Session-based 🍪 JWT / Token-based 🔑
Trạng thái Stateful (server lưu) Stateless (client lưu)
Khả năng revoke ✅ Ngay lập tức ❌ Khó (cần blacklist)
Scale ngang ⚠️ Cần Redis/Store tập trung ✅ Dễ dàng
Phù hợp Mobile/API ❌ Không lý tưởng ✅ Tốt
Tải server ⚠️ Cao hơn (lookup DB/Redis) ✅ Thấp hơn (verify locally)
Bảo mật mặc định ✅ Cookie HttpOnly an toàn hơn ⚠️ Token trong localStorage dễ bị XSS
Khi nào dùng Web app truyền thống, banking, admin panel SPA, Mobile app, Microservices, API public

🧪 9. Ví dụ code (Laravel)

// Đăng nhập — tạo session
public function login(Request $request)
{
    $credentials = $request->only('email', 'password');
    
    if (Auth::attempt($credentials)) {
        // Tạo session ID mới (tránh Session Fixation)
        $request->session()->regenerate();
        
        return redirect()->intended('/dashboard');
    }
    
    return back()->withErrors(['email' => 'Thông tin đăng nhập không đúng.']);
}

// Đăng xuất — hủy session
public function logout(Request $request)
{
    Auth::logout();
    
    $request->session()->invalidate();   // Hủy session
    $request->session()->regenerateToken(); // Tạo CSRF token mới
    
    return redirect('/login');
}

// Middleware kiểm tra session
// Laravel tự xử lý qua middleware 'auth'
Route::get('/dashboard', [DashboardController::class, 'index'])
    ->middleware('auth');

📝 10. Khi nào nên dùng Session-based Auth?


🔗 Tham khảo thêm

Bài viết liên quan

Đang cập nhật...