Bỏ qua đến nội dung
KhaiziNam Blog KhaiziNam Blog
Quay lại
Read in English

Session vs JWT: Toàn Bộ Lý Thuyết Và Câu Hỏi Phỏng Vấn Hay Gặp Nhất Mà Junior Cần Nắm Chắc

Gần như 100% buổi phỏng vấn backend có hỏi về authentication — và câu hỏi kinh điển nhất vẫn là “em phân biệt Session và JWT như thế nào, khi nào dùng cái nào?” Nghe quen nhưng rất nhiều Junior trả lời sai hoặc trả lời đúng một nửa. Bài này tôi tổng hợp lại toàn bộ lý thuyết cốt lõi, phân tích sâu từng điểm khác biệt, và liệt kê đúng những câu hỏi phỏng vấn thực tế xoay quanh chủ đề này — kèm câu trả lời chi tiết để bạn không bị bất ngờ.

Mục Lục

1. Bản chất của Authentication — Tại sao cần Session hay JWT?

2. Session là gì — Cơ chế hoạt động và lưu trữ ở đâu

3. JWT là gì — Cấu trúc, cơ chế và lưu trữ ở đâu

4. So sánh chi tiết Session vs JWT — Giống nhau, khác nhau

5. Khi nào dùng Session, khi nào dùng JWT

6. Những câu hỏi phỏng vấn thực tế và cách trả lời chuẩn

7. Những sai lầm hay gặp khi implement và trả lời phỏng vấn

8. FAQ — Câu hỏi đào sâu nhất về Session và JWT


Bản Chất Của Authentication — Tại Sao Cần Session Hay JWT?

Trước khi so sánh, cần hiểu tại sao vấn đề này tồn tại. HTTP là stateless — mỗi request hoàn toàn độc lập, server không tự nhớ bạn đã đăng nhập ở request trước. Sau khi user nhập đúng username/password, server cần một cơ chế để chứng minh danh tính của user ở những request tiếp theo mà không bắt họ đăng nhập lại.

Đây là bài toán Authentication State Management — và có hai trường phái giải quyết hoàn toàn khác nhau về triết lý:

Hiểu đúng triết lý này là nền tảng để trả lời mọi câu hỏi phỏng vấn liên quan. Mọi điểm khác biệt giữa Session và JWT đều bắt nguồn từ sự lựa chọn kiến trúc căn bản này.

Session Là Gì — Cơ Chế Hoạt Động Và Lưu Trữ Ở Đâu

Session Là Gì — Cơ Chế Hoạt Động Và Lưu Trữ Ở Đâu

Session Là Gì — Cơ Chế Hoạt Động Và Lưu Trữ Ở Đâu

Session là cơ chế trong đó server tạo ra một bản ghi lưu trạng thái đăng nhập của user, gán cho nó một ID ngẫu nhiên duy nhất (Session ID), rồi gửi Session ID đó về client qua cookie. Các request tiếp theo, client gửi kèm Session ID — server dùng ID đó để tra cứu bản ghi session và xác định đây là ai.

Luồng hoạt động của Session từng bước
  1. User gửi POST /login với username + password.
  2. Server xác thực credentials, nếu đúng thì tạo một session record: { user_id: 42, role: "admin", created_at: "..." }
  3. Server lưu session record vào storage (file, database, Redis…) với key là Session ID ngẫu nhiên, ví dụ: abc123xyz
  4. Server trả về response với header Set-Cookie: session_id=abc123xyz; HttpOnly; Secure
  5. Browser tự động lưu cookie và gửi kèm mọi request tiếp theo.
  6. Server nhận request, đọc cookie lấy session_id, tra cứu storage → biết đây là user 42 với role admin.
  7. Khi logout, server xóa session record khỏi storage → Session ID đó vô hiệu ngay lập tức.
Session lưu ở đâu — Phía server

Đây là câu hỏi phỏng vấn hay bị hỏi nhất trong phần Session. Session data được lưu phía server, không phải phía client. Client chỉ giữ Session ID (một chuỗi ngẫu nhiên vô nghĩa). Có nhiều lựa chọn storage cho session data:

Session ID lưu ở đâu — Phía client

Phía client, Session ID được lưu trong cookie. Cookie nên được thiết lập với các flag bảo mật:

// Laravel session config — config/session.php ‘driver’ => env(‘SESSION_DRIVER’, ‘redis’), ‘lifetime’ => 120, // phút ‘expire_on_close’ => false, ‘encrypt’ => true, // mã hóa session data trước khi lưu ‘cookie’ => ‘laravel_session’, ‘secure’ => true, // chỉ HTTPS ‘http_only’ => true, // không cho JS đọc ‘same_site’ => ‘lax’,

JWT Là Gì — Cấu Trúc, Cơ Chế Và Lưu Trữ Ở Đâu

JWT Là Gì — Cấu Trúc, Cơ Chế Và Lưu Trữ Ở Đâu

JWT Là Gì — Cấu Trúc, Cơ Chế Và Lưu Trữ Ở Đâu

JWT (JSON Web Token) — đọc là “jot” — là một chuẩn mở (RFC 7519) định nghĩa cách truyền thông tin an toàn giữa các bên dưới dạng JSON object được ký số. Điểm cốt lõi: server không lưu gì — toàn bộ thông tin nằm trong token, server chỉ cần verify chữ ký để xác thực.

Cấu trúc của một JWT

JWT gồm 3 phần, ngăn cách bởi dấu chấm: Header.Payload.Signature

eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9 . eyJ1c2VyX2lkIjo0Miwicm9sZSI6ImFkbWluIiwiZXhwIjoxNzE2MDAwMDAwfQ . SflKxwRJSMeKKF2QT4fwpMeJf36POk6yJV_adQssw5c

Mỗi phần là Base64Url encoded JSON:

Header: Chứa loại token và thuật toán ký.

{ “alg”: “HS256”, “typ”: “JWT” }

Payload (Claims): Chứa thông tin user và metadata. Payload không được mã hóa — chỉ encoded Base64, ai cũng decode được. Không bao giờ để thông tin nhạy cảm như password vào đây.

{ “user_id”: 42, “role”: “admin”, “exp”: 1716000000, “iat”: 1715913600 }

Signature: Được tạo bằng cách ký Header + Payload với secret key. Đây là phần đảm bảo token không bị giả mạo — nếu ai thay đổi Payload, signature sẽ không còn khớp.

HMACSHA256(base64(header) + ”.” + base64(payload), SECRET_KEY)

Luồng hoạt động của JWT từng bước
  1. User gửi POST /login với credentials.
  2. Server xác thực, tạo JWT với payload chứa user_id, role, exp (expiry time), ký bằng secret key.
  3. Server trả token về cho client. Server không lưu gì.
  4. Client lưu token và gửi kèm mọi request tiếp theo trong header: Authorization: Bearer <token>
  5. Server nhận request, verify signature bằng secret key → nếu hợp lệ thì đọc payload, biết đây là user 42.
  6. Không cần query database hay bất kỳ storage nào để xác thực.
JWT lưu ở đâu — Phía client

Đây là câu hỏi nhiều người trả lời sai. JWT được lưu phía client, và có nhiều lựa chọn với trade-off khác nhau:

Không có lựa chọn hoàn hảo — mỗi cách đánh đổi giữa bảo mật, UX và độ phức tạp implement. Đây chính là lý do câu hỏi này hay xuất hiện trong phỏng vấn senior hơn junior.

Access Token và Refresh Token

Trong thực tế, JWT thường dùng theo cặp để cân bằng bảo mật và UX:

// Laravel Sanctum / Passport — tạo token $user = User::find(1);

// Access token — hết hạn sau 60 phút $accessToken = $user->createToken(‘access-token’, [’*’], now()->addHour())->plainTextToken;

// Refresh token — hết hạn sau 30 ngày $refreshToken = $user->createToken(‘refresh-token’, [‘refresh’], now()->addDays(30))->plainTextToken;

So Sánh Chi Tiết Session vs JWT — Giống Nhau, Khác Nhau

Điểm giống nhau
Điểm khác nhau cốt lõi

Khi Nào Dùng Session, Khi Nào Dùng JWT

Đây là câu hỏi không có đáp án tuyệt đối — phụ thuộc vào yêu cầu cụ thể của hệ thống. Tuy nhiên có các nguyên tắc rõ ràng để quyết định:

Dùng Session khi
Dùng JWT khi
Trường hợp nên dùng cả hai kết hợp

Đây là pattern ít Junior biết nhưng rất phổ biến trong thực tế: Session cho web app, JWT cho API. Ví dụ: một hệ thống e-commerce có web app (dùng Session + Cookie) và mobile app + third-party API (dùng JWT). Cả hai chia sẻ cùng backend nhưng dùng cơ chế authentication khác nhau tùy client type.

Trong Laravel, đây là lý do có cả auth:sanctum (hỗ trợ cả Session-based và Token-based) và auth:api (JWT thuần).

Những Câu Hỏi Phỏng Vấn Thực Tế Và Cách Trả Lời Chuẩn

Đây là phần tôi tổng hợp lại từ kinh nghiệm thực tế — những câu hỏi thực sự xuất hiện trong buổi phỏng vấn, không phải câu hỏi sách vở.

Câu 1: “Em giải thích Session và JWT khác nhau như thế nào?”

Đây là câu mở đầu, nên trả lời bằng cách nhấn vào triết lý kiến trúc trước, rồi mới đến chi tiết kỹ thuật:

“Session là stateful — server lưu trạng thái đăng nhập, client chỉ giữ một cái ID để tra cứu. JWT là stateless — server không lưu gì, toàn bộ thông tin nằm trong token client giữ, server chỉ verify chữ ký. Từ sự khác biệt căn bản này dẫn đến các trade-off về scalability, revocation, và phù hợp với loại ứng dụng khác nhau.”

Câu 2: “Session lưu ở đâu, JWT lưu ở đâu?”

Câu này có hai tầng cần trả lời rõ — phía server và phía client:

“Session data lưu phía server — có thể là file, database, hoặc Redis. Client chỉ lưu Session ID trong cookie. JWT không lưu gì phía server. Phía client, JWT có thể lưu trong localStorage, sessionStorage, hoặc HttpOnly cookie — mỗi cách có trade-off bảo mật khác nhau. Bảo mật nhất là in-memory kết hợp với Refresh Token trong HttpOnly cookie.”

Câu 3: “Nếu user bị ban, làm thế nào để vô hiệu hóa token JWT ngay lập tức?”

Đây là câu hỏi bẫy — nhiều Junior không biết đây là điểm yếu cố hữu của JWT. Câu trả lời đúng:

“JWT không thể revoke trước khi hết hạn một cách thuần túy stateless. Có hai cách xử lý: Một là dùng short-lived access token (15 phút) — user bị ban thì tối đa 15 phút sau token tự hết hạn. Hai là maintain một JWT blacklist trên Redis — khi revoke, lưu jti (JWT ID) vào blacklist, mỗi request check xem jti có trong blacklist không. Cách hai về bản chất làm JWT trở thành semi-stateful, mất một phần lợi thế ban đầu.”

Câu 4: “Tại sao không nên lưu JWT trong localStorage?”

“localStorage có thể bị đọc bởi bất kỳ JavaScript nào chạy trên trang — bao gồm cả mã độc inject qua XSS. Nếu app bị XSS, attacker chạy localStorage.getItem('token') là lấy được JWT ngay. Ngược lại, HttpOnly cookie không đọc được qua JavaScript — XSS không lấy được. Tuy nhiên HttpOnly cookie lại dễ bị CSRF hơn, nên cần thêm CSRF token protection.”

Câu 5: “Payload của JWT có bị đọc không? Có an toàn không?”

“Payload của JWT chỉ được Base64Url encode, không mã hóa — ai cũng decode được. Tính bảo mật của JWT không nằm ở việc giữ payload bí mật, mà ở chữ ký (signature) — đảm bảo payload không bị giả mạo. Vì vậy tuyệt đối không lưu thông tin nhạy cảm như password, credit card vào JWT payload.”

Câu 6: “Khi nào thì dùng Session, khi nào dùng JWT? Anh đang xây một admin panel nội bộ, em sẽ dùng cái nào?”

“Admin panel nội bộ, tôi sẽ dùng Session. Lý do: admin panel thường là web app server-render hoặc SPA trên cùng domain, không có yêu cầu cross-domain authentication. Quan trọng hơn, admin cần khả năng revoke session ngay lập tức — nếu phát hiện tài khoản bị xâm phạm, cần logout ngay, không thể đợi token hết hạn. Session cho phép làm điều đó đơn giản và an toàn hơn.”

Câu 7: “HS256 và RS256 trong JWT khác nhau như thế nào?”

Câu này ít gặp ở Junior nhưng nếu bị hỏi:

“HS256 dùng symmetric key — cùng một secret key để ký và verify. Tất cả bên cần verify đều phải biết secret key — không phù hợp khi nhiều service cần verify độc lập. RS256 dùng asymmetric key — private key để ký (chỉ auth server biết), public key để verify (bất kỳ service nào cũng có thể có). Microservices thường dùng RS256 vì các service chỉ cần public key để verify mà không cần biết private key.”

Những Sai Lầm Hay Gặp Khi Implement Và Trả Lời Phỏng Vấn

FAQ — Câu Hỏi Đào Sâu Nhất Về Session Và JWT

Hỏi: JWT có thể dùng với Laravel không, hay chỉ dùng Session?

Đáp: Laravel hỗ trợ cả hai. Laravel Sanctum hỗ trợ cả Session-based authentication (cho SPA cùng domain) và Token-based (cho mobile app, API). Laravel Passport implement OAuth 2.0 đầy đủ với JWT. Package tymon/jwt-auth là lựa chọn phổ biến khác cho JWT thuần. Mặc định Laravel dùng Session cho web routes và Token cho API routes.

Hỏi: Refresh Token hoạt động như thế nào, tại sao cần hai loại token?

Đáp: Access Token thời gian sống ngắn để giới hạn thiệt hại nếu bị lộ, nhưng ngắn quá thì user phải đăng nhập lại liên tục. Refresh Token thời gian sống dài, chỉ dùng để lấy Access Token mới khi hết hạn. Client tự động gọi refresh endpoint khi nhận 401, lấy Access Token mới mà user không cần thao tác gì. Refresh Token nên lưu HttpOnly cookie, Access Token nên lưu in-memory để bảo mật tối đa.

Hỏi: Microservices nên dùng JWT hay Session?

Đáp: JWT là lựa chọn tiêu chuẩn cho microservices. Lý do: các service không share cùng session store, mỗi service cần tự verify request độc lập. Với JWT dùng RS256, auth service giữ private key để ký token, còn lại các service chỉ cần public key để verify. Không cần gọi auth service cho mỗi request — service A tự verify JWT và đọc claims mà không cần I/O thêm.

Hỏi: Có thể dùng cả Session lẫn JWT trong cùng một ứng dụng không?

Đáp: Hoàn toàn được và khá phổ biến trong thực tế. Laravel cho phép định nghĩa nhiều guard khác nhau trong config/auth.php: web guard dùng Session cho browser, api guard dùng token cho mobile và third-party client. Middleware auth:webauth:api áp dụng riêng biệt cho từng nhóm routes. Đây là pattern phù hợp cho hệ thống vừa có web app vừa có REST API.

Hỏi: Nếu secret key JWT bị lộ, phải làm gì?

Đáp: Đây là tình huống nghiêm trọng — attacker có thể forge bất kỳ token nào với secret key đó. Cần làm ngay: đổi secret key mới, deploy lại service. Toàn bộ token cũ ký bằng key cũ sẽ fail verify ngay lập tức — tất cả user bị logout và phải đăng nhập lại. Để giảm rủi ro, nên rotate secret key định kỳ và dùng key versioning trong payload ("kid": "v2") để support transition period.

Tổng Kết — Cách Nhớ Để Không Bao Giờ Nhầm

Sau tất cả lý thuyết, có một cách nhớ đơn giản nhất: Session giống thẻ gửi xe — bạn giữ số thẻ, bãi xe giữ xe thật. JWT giống bằng lái xe — bạn giữ toàn bộ thông tin, ai cũng có thể kiểm tra mà không cần gọi về trung tâm.

Chọn Session khi bạn cần kiểm soát tuyệt đối — thu hồi ngay, audit đầy đủ, dữ liệu luôn mới nhất. Chọn JWT khi bạn cần linh hoạt — nhiều client, nhiều domain, scale ngang không cần shared storage.

Xem thêm các bài viết thuộc Series Phỏng vấn

Bước tiếp theo thực tế: Mở một project Laravel cũ của bạn, thử implement cả hai cơ chế — Session cho web routes, Sanctum token cho API routes. Viết một endpoint /me hoạt động với cả hai guard. Khi bạn tự tay implement và debug lỗi thực tế, phỏng vấn về chủ đề này sẽ không còn là thách thức nữa.

Tác giả: Nguyễn Hữu Khải

21/04/2026

Xem thêm: 


Chia sẻ bài viết:

Bài viết liên quan

Mức lương fresher junior IT 2026 - PHP, NodeJS, React, Flutter thực tế

Bảng lương thực tế của fresher và junior IT Việt Nam năm 2026 theo từng stack - PHP/Laravel, Node.js, ReactJS, Flutter - kèm cách đọc con số để biết bạn đang ở đâu trên thị trường, dù bạn chưa đi làm hay đã đi làm 1-2 năm.

Portfolio cho dev junior - cần có gì để được chú ý

Portfolio developer junior là tập hợp các project thực tế, kỹ năng và thông tin nghề nghiệp mà bạn trình bày để nhà tuyển dụng đánh giá năng lực - thay thế cho phần kinh nghiệm làm việc còn trống trên CV. Với fresher và junior developer, portfolio không phải thứ "có thì tốt" - đó là bằng chứng duy nhất bạn có thể đưa ra để chứng minh bạn thực sự biết làm việc, không chỉ biết lý thuyết.

Cover Letter Fresher IT: Cách Viết Để Được Gọi Phỏng Vấn

Cách viết cover letter cho fresher IT khi chưa có kinh nghiệm, kèm mẫu thực tế, cấu trúc chuẩn và mẹo tăng tỷ lệ vượt qua vòng lọc CV.

Ngôn ngữ cơ thể trong phỏng vấn — những điều vô tình mất điểm

Ngôn ngữ cơ thể phỏng vấn IT là tập hợp những tín hiệu phi ngôn ngữ — tư thế, ánh mắt, cử chỉ tay, giọng điệu — mà nhà tuyển dụng quan sát song song với câu trả lời kỹ thuật của bạn. Hiểu và kiểm soát tốt những tín hiệu này giúp bạn tạo ấn tượng chuyên nghiệp ngay từ những giây đầu tiên bước vào phòng phỏng vấn.

Cách đặt câu hỏi ngược khi phỏng vấn IT — đừng chỉ hỏi lương

Hướng dẫn cách đặt câu hỏi ngược khi phỏng vấn IT dành cho fresher và junior developer — tại sao phần "bạn có câu hỏi gì không" quan trọng hơn bạn nghĩ, 20+ câu hỏi thực tế phân loại theo mục đích, những câu tuyệt đối không nên hỏi, và cách chọn đúng câu hỏi theo từng vòng phỏng vấn.

Vì sao bạn chọn ngành IT — câu trả lời tạo ấn tượng với HR khi phỏng vấn

Hướng dẫn cách trả lời câu hỏi "vì sao bạn chọn ngành IT" trong phỏng vấn — phân tích điều HR thực sự muốn nghe, framework xây dựng câu trả lời theo từng hoàn cảnh, script mẫu cho fresher và career changer, cùng các lỗi phổ biến khiến câu trả lời nghe sáo rỗng và không đáng tin.

Điểm yếu lớn nhất của bạn là gì — cách trả lời không bị loại ngay khi phỏng vấn IT

Hướng dẫn cách trả lời câu hỏi "điểm yếu lớn nhất của bạn là gì" trong phỏng vấn IT — phân tích tại sao câu này là bẫy, framework trả lời 3 bước, script mẫu cho fresher và junior developer, cùng danh sách lỗi hay gặp khiến ứng viên bị loại ngay lập tức.

Câu Hỏi Phỏng Vấn ReactJS Junior: 30+ Câu Thực Tế Kèm Đáp Án Chuẩn 2026

Tổng hợp 30+ câu hỏi phỏng vấn ReactJS junior hay gặp nhất năm 2026 — từ Virtual DOM, hooks, state management đến performance optimization — kèm đáp án chi tiết và ví dụ code giúp bạn tự tin vượt qua mọi vòng technical interview.Bạn đã học React được vài tháng, build được project, nhưng mỗi lần vào phỏng vấn lại bị hỏi những thứ không có trong tutorial nào bạn từng đọc? "useEffect cleanup function

Refresh Token Node.js và Laravel: Hướng Dẫn Implement Chuẩn Production 2026

Hướng dẫn implement Refresh Token hoàn chỉnh cho cả Node.js (Express) và Laravel PHP — từ thiết kế database, viết API endpoint, xử lý rotation, đến các lỗi thường gặp — giúp developer xây hệ thống JWT authentication chuẩn production trong năm 2026.

Session vs JWT: Developer Nên Chọn Cái Nào? So Sánh Thực Tế 2026

Phân tích chi tiết Session và JWT theo 6 tiêu chí kỹ thuật thực tế - kiến trúc, revocation, scaling, hiệu năng, bảo mật và độ phức tạp — giúp developer đưa ra quyết định đúng cho từng loại dự án trong năm 2026.


Bài trước
Cách Deploy Node.js và React Lên Hosting Linux Bằng Nginx Reverse Proxy — Hướng Dẫn Đầy Đủ PM2 + SSL 2025
Bài tiếp theo
Phỏng Vấn Junior Outsource: Từ AI Workflow, Dependency Injection Đến Bài Toán Redis Chặn Concurrent Edit