Authentication: Làm thế nào để quản lý phiên đăng nhập

Quản lý phiên đăng nhập hay còn gọi là Session management là một chủ đề đơn giản nhưng do cách sử dụng ngôn ngữ của giới lập trình đã khiến nó trở nên rối rắm và khó hiểu. Chúng ta ngập trong hàng chục thuật ngữ khác nhau và thật sự còn không biết nên định nghĩa như thế nào là chuẩn hoá.
Stateful session management
Theo định nghĩa: stateful là một chuỗi các request liên quan đến cùng một User, khác với Stateless là các request sẽ độc lập với nhau, không có sự liên quan. Session (phiên) về bản chất là hành động stateful. Các web app hiện đại đều có những tính năng yêu cầu phải lưu trữ thông tin hoặc trạng thái của từng User trong suốt 1 phiên đăng nhập.
Lấy ví dụ như tính năng Giỏ hàng trong các hệ thống Thương mại điện tử: Giỏ hàng cần được ghi nhớ lại trong toàn bộ phiên hoạt động của người dùng để nhỡ may người dùng có thực hiện Đặt hàng thì ta đã có sẵn danh sách hàng hoá người dùng đã để vào trong Giỏ hàng.
Vậy nên ta sinh ra một thuật ngữ gọi là Session và lưu nó ở đâu đó. Ở trong ví dụ trên, Giỏ hàng chính là Session. Tất nhiên dễ dàng nhất chúng ta hoàn toàn có thể lưu Object Session này ở back-end, và trong ngữ cảnh authentication đó là cái mà người ta hay gọi là Session-based authentication. Nhưng chính xác thì nên được gọi là Stateful session management. Cách này hoàn toàn hợp lý, thật là nhanh gọn đơn giản dễ hiểu.
Lợi thế của stateful session management
Dễ hiểu, dễ xoay xở với các use case mở rộng do tập trung mọi thứ ở back-end
Dễ thu hồi session: Sessions dễ dàng bị vô hiệu ở server-side (ví dụ., logout, password thay đổi, hoặc đăng nhập đáng nghi) by simply deleting the session record. The effect is immediate.
Client Data nhỏ: Client chỉ phải lưu session id được trả ra bởi server, phù hợp với các client gọn nhẹ không có logic phức tạp (như web MVC pattern).
Vấn đề với stateful session management
Rất nhiều người thấy rằng stateful server, hay lưu Session ở back-end là một thảm hoạ.
Trong ví dụ Giỏ hàng của Hệ thống thương mại điện tử, back-end server sẽ phải theo dõi hàng triệu giỏ hàng cùng 1 lúc trong các phiên đăng nhập khác nhau. Và trong rất nhiều trường hợp, User sẽ bỏ rơi giỏ hàng đó mà không hề mua hàng. Chúng ta sẽ tốn rất nhiều tài nguyên server để lưu trữ rất nhiều data rác.
Tiếp đến, việc mở rộng theo chiều ngang (horizontal scaling) cũng là một thử thách. Có 2 cách để xử lý:
Sticky sessions: Đảm bảo user luôn luôn được điều hướng đến cùng một server mà ở đó lưu data session của họ. Tuy nhiên, điều này có thể dẫn đến sự mất cân bằng khi phân chia lượng request cho các server
Shared session storage: Tập trung tất cả dữ liệu Session về một database (hoặc cache) được chia sẻ bởi các server. Tuy nhiên, giải pháp này có sự phức tạp của nó và có thể dẫn đến Single Point Of failure, cần bỏ nhiều công sức.
Ngoài ra, nếu lưu session-id ở cookie thì chúng ta cũng nên để ý đến vấn đề bảo mật khỏi tấn công Cross-site request forgery (CSRF), nhưng sẽ tránh được tấn công Cross-site scripting (XSS)
Stateless session management
Trong ngữ cảnh của authentication còn gọi là stateless authentication. Đây là một kỹ thuật được sử dụng nhiều ở các client phức tạp như Single-page web app hoặc mobile app, hay gặp nhất là **Token-based authentication (**token chính là session). Stateless là các request sẽ độc lập với nhau, không có sự liên quan. Đúng thế, lúc này server sẽ được giải phóng khỏi việc duy trì data giữa các request, và lúc này chúng ta không có session. Chúng ta sẽ đẩy việc lưu trữ data của session về client. Và Client sẽ có cơ chế lưu session data ở client-side và gửi session data cho server trong mọi request.
Lợi thế của stateless session management
Khả năng mở rộng tuyệt vời: Servers không cần phải lưu session data. Đối với token-based authentication, bất kỳ instance nào có secret key đều validate được phiên đăng nhập và truy cập session data do được gửi toàn bộ kèm trong request.
Giảm Server Load: Không cần lưu trữ session và truy vấn. Đối với Token, việc kiểm tra là dùng phép toán, không cần lưu trữ ở database (nếu dùng database).
Decoupling: Phục vụ rất tốt cho microservices khi các service độc lập với nhau cần authenticate và không cần phụ thuộc chung vào một trung tâm chứa dữ liệu session.
Vấn đề
Sự phức tạp khi Bảo mật session data (token): Nếu token như JWT được lưu client-side, chúng sẽ dễ bị đánh cắp bởi các phương pháp tấn công như Cross-Site Scripting (XSS), Cross site request forgery (CSRF). Cần có những hiểu biết sâu hơn về security để cài đặt các phương pháp phòng chống.
Sự phức tạp khi muốn thu hồi session: Tokens hợp lệ cho đến khi hết hạn. Thu hồi một token ngay khi chúng hết hạn cần có giải pháp đi kèm như duy trì server-side blocklist/denylist (lại yêu cầu lưu data phía server). Một phương pháp khác là giảm thời gian hiệu lực của token và sài cơ chế refresh token.
Dung lượng Token Size: Session data đôi khi chứa rất nhiều thứ, tăng bandwidth cho mỗi request.
Phải cài đặt thêm mã nguồn phía client: Cần viết code phía client để lưu trữ session data (token) an toàn và gắn vào mọi request.
Kết luận
Trong bài viết này chúng ta đã điểm qua cách để quản lý session. Thông thường có 2 cách để quản lý Session: là Stateful và Stateless. Trong thuật ngữ phổ biến của Authentication mọi người sẽ gọi nó bằng 2 cách: Session based authentication tương đương stateful session management và Token based authentication (stateless session managemement). Mỗi cách có ưu nhược điểm riêng, chúng ta sẽ cần cân nhắc đánh đổi tuỳ trường hợp mà biết nên sử dụng phương pháp nào.
Subscribe to my newsletter
Read articles from Anh Phan directly inside your inbox. Subscribe to the newsletter, and don't miss out.
Written by
