Nội dung bài viết
Video học lập trình mỗi ngày
Ngoài ra một kịch bản khác nữa được đưa ra ngoài chuyện Logout. Ví dụ như khi login thì sao?
Bài phỏng vấn này được đưa vào Series: (Đánh bại Senior) Kỹ năng trả lời phỏng vấn của các level
Cụ thể là thay vì trước tôi có thể sử dụng trên
iPhone
, giờ đây một một thời gian tôi có thể login và sử dụng trên các devices nhưiPad, iMac
. Và điều gì diễn ra khi tôi logout trên thiết bị iPhone, nhưng việc hoạt động của các thiết bị còn lại vẫn hoạt động bình thường?
Nếu có thời gian vui lòng xem cách triển khai và thực tế khi sử dụng: Đánh bại Senior: JWT Logout đơn giản - mà không làm ảnh hưởng đến các thiết bị khác cùng tài khoản.
Câu nói hay:
Đừng hoảng loạn, hãy tập trung vào những gì có thể thay đổi Khi đối diện với một vấn đề, phản ứng tự nhiên của con người là lo lắng, sợ hãi và phóng đại hậu quả. Nhưng thực tế, hầu hết những điều ta lo lắng không tệ như ta nghĩ.
Kịch bản một User sử dụng nhiều Devices
Trước đây hệ thống API banvetau của chúng tôi chỉ đáp ứng với một số lượng user thấp vào giờ cao điểm cho nên chỉ cho phép một User có thể sử dụng được một device cùng một thời điểm
, lúc đó việc quản lýlogin, logout
và thậm chí chức năng quên mật khấu được quản lý rất tốt ở thời điểm này.
Với việc sử dụng JWT
vào hệ thống vừa đơn giản vừa đảm bảo phòng ngừa rủi ro cho nên việc user logout ra khỏi thiết bị thì chúng tôi quản lý rất tốt. Khi User logout thì hệ thống sẽ tự động đưa token đã cấp phát cho user khi login thành công và đưa vào một nơi mà chúng tôi thường gọi là tokenBlackList
.
Tất nhiên token sẽ không hoạt động nếu TTL = 0
. Điều này có nghĩa là mỗi token đều có thời gian sử dụng, nếu hết hạn thì không còn giá trị sử dụng.
try {
const decoded = jwt.verify(token, JWT_SECRET);
// Check the blacklist
const isTokenExistsBlackList = await redis.get(`TOKEN_BLACK_LIST_${decoded.uid}_${decoded.jit}`);
if (isTokenExistsBlackList) {
return res.status(401).json({ message: 'Token revoked' });
}
req.user = decoded; // Save user info into the request object
next();
} catch (error) {
if (error.name === 'TokenExpiredError') {
return res.status(401).send('Token expired');
} else if (error.name === 'JsonWebTokenError') {
return res.status(401).send('Invalid token');
}
return res.sendStatus(403); // Forbidden (invalid token)
}
Tôi nghĩa bạn nên xem thêm phần Jwt và các kịch bản sử dụng? Đừng quá lạm dụng
Tất cả lập trình viên đều biết rằng một khi jwt token
được tạo và cấp phát tới User thì hệ thông không thể thu hồi theo cách trực tiếp và không thể sửa đổi được trên token đó, vì vậy đó là một nhược điểm bên cạnh những ưu điểm lớn khác. Việc này giống như một khi bắn mũi tên ra thì không thể thu hồi được đúng không?
Nói về cơ chế thì cách hoạt động của kịch bản này rất dễ hiểu đó là khi logout thì token này đã có trong tokenBlackList
vì vậy khi một ai đó vô tình lấy lại token này để sử dụng or token này bị rò rỉ (leak) và thời gian token này chưa hết hạn thì trước hết nó phải đi vào trong cơ chế middleware( một AOP - Lập trình hướng khía cạnh trong Nest và JAVA còn trong Nodejs hay Got thì gọi là middleware) thì lúc này nó sẽ check xem token này đã có trong tokenBlackList()
hay chưa, trước khi nó cho phép truy cập vào tài nguyên của API banvetau nếu return true
và ngược lại.
Ngoài ra hiện tại có rất nhiều cách triển khai nhưng một số cách đã lỗi thời, và một số cách được hưỡng dẫn bởi những con AI đưa ra rất rủi ro, vì nó đã có thể sử dụng token trong việc lưu trữ để kiểm tra cho sự tồn tại của token này khi User Logout.
Điều đó đối với hệ thống bán vé tàu thì sẽ không được phép lưu trữ token của bất kỳ user nào trên hệ thống, đó là nguyên tắc cho dù bạn đã mã hoá với nhiều định dạng khác nhau tương tự với việc lưu trữ email, số điện thoại hay số tài khoản sẽ được mã hoá, và nếu đã là nguyên tắc thì không thể vi phạm.
Vì vậy tôi sẽ show cho các bạn một trong những làm hiện nay rất đơn giản nhưng mang lại hiệu quả rất cao so với các cách thông thường mà hầu hết các dự án đang sử dụng.
Một User và nhiều Devices
Sau nhiều lần thất bại thì hệ thống cũng đã nâng cấp Hệ thống chịu tải lên đến hàng chục ngàn user truy cập cùng một lúc - có source các bạn có thể xem ở playlist JAVA xem cách chúng tôi cải thiện hiệu suất lên như thế nào với chí phí hầu như bằng 0 thì lúc này api sau khi test stress thành công thì cho phép một user có thể truy cập một lúc được nhiều thiết và sử dụng để quản lý ticket và tiện hơn cho việc mua vé tàu ở cao điểm khi diễn ra.
Cụ thể là thay vì trước tôi có thể sử dụng trên
iPhone
, giờ đây một một thời gian tôi có thể login và sử dụng trên các devices nhưiPad, iMac
. Và điều gì diễn ra khi tôi logout trên thiết bị iPhone, nhưng việc hoạt động của các thiết bị còn lại vẫn hoạt động bình thường?
Với câu hỏi dễ này thì điều đầu tiên tất cả các lập trình viên đều nghĩ rằng, chức năng này triển khai không khó, chỉ cần thiết kế là mỗi lần user login trên mỗi device thì sẽ tạo ra một jwt token riêng biệt.
Đúng vậy, quay trở lại cách đặt key trong tokenBlackList
trước đây chúng ta có cú pháp quản lý những token của user nào đã logout:
TOKEN_BLACK_LIST_123: 1,
TOKEN_BLACK_LIST_234: 1
Mời các bạn cùng thảo luận và xem cách triển khai: Đánh bại Senior: JWT Logout đơn giản - mà không làm ảnh hưởng đến các thiết bị khác cùng tài khoản.