Đăng xuất
Khi người dùng đăng xuất khỏi một trang web, họ thể hiện mong muốn thoát hoàn toàn khỏi trải nghiệm được cá nhân hoá cho người dùng. Do đó, điều quan trọng là phải tuân thủ chặt chẽ nhất có thể với mô hình tư duy của người dùng. Ví dụ: một trải nghiệm đăng xuất đúng cách cũng phải tính đến mọi thẻ mà người dùng có thể đã mở trước khi họ quyết định đăng xuất.
Có thể tóm tắt yếu tố chính dẫn đến trải nghiệm đăng xuất tuyệt vời là nhất quán trên các khía cạnh hình ảnh và trạng thái của trải nghiệm người dùng. Hướng dẫn này cung cấp lời khuyên cụ thể về những điều cần chú ý và cách để có được trải nghiệm đăng xuất tốt.
Những điểm chính cần cân nhắc
Khi triển khai chức năng đăng xuất trên trang web của bạn, hãy chú ý đến những khía cạnh sau để đảm bảo quy trình đăng xuất suôn sẻ, an toàn và trực quan:
- Trải nghiệm người dùng đăng xuất rõ ràng và nhất quán: Cung cấp nút hoặc đường liên kết đăng xuất rõ ràng và nhất quán, dễ nhận biết và nhất quán trên toàn bộ trang web. Tránh sử dụng các nhãn không rõ ràng hoặc ẩn chức năng đăng xuất trong các trình đơn, trang con hoặc các vị trí không trực quan khác.
- Lời nhắc xác nhận: Triển khai lời nhắc xác nhận trước khi hoàn tất quy trình đăng xuất. Điều này có thể giúp ngăn người dùng vô tình đăng xuất và cho phép người dùng xem xét lại xem họ có thực sự cần đăng xuất hay không, ví dụ: nếu họ thường xuyên khoá thiết bị của mình bằng mật khẩu mạnh hoặc cơ chế xác thực khác.
- Xử lý nhiều thẻ: Nếu người dùng đã mở nhiều trang trên cùng một trang web trong các thẻ khác nhau, hãy đảm bảo rằng việc đăng xuất khỏi một thẻ cũng sẽ cập nhật tất cả các thẻ đang mở khác trên trang web đó.
- Chuyển hướng đến một trang đích an toàn: Sau khi đăng xuất thành công, hãy chuyển hướng người dùng đến một trang đích bảo mật cho biết rõ rằng họ không còn đăng nhập nữa. Tránh chuyển hướng người dùng đến các trang có thông tin cá nhân hoá. Tương tự, hãy đảm bảo rằng các thẻ khác cũng không còn phản ánh trạng thái đã đăng nhập. Ngoài ra, hãy đảm bảo rằng bạn không tạo lệnh chuyển hướng mở mà kẻ tấn công có thể lợi dụng.
- Dọn dẹp phiên: Sau khi người dùng đăng xuất, hãy xoá hoàn toàn mọi dữ liệu nhạy cảm về phiên của người dùng, cookie hoặc các tệp tạm thời được liên kết với phiên hoạt động của người dùng đó. Điều này giúp ngăn chặn hành vi truy cập trái phép vào thông tin người dùng hoặc hoạt động tài khoản, đồng thời cũng ngăn trình duyệt khôi phục các trang có thông tin nhạy cảm từ nhiều bộ nhớ đệm, đặc biệt là bộ nhớ đệm cho thao tác tiến/lùi.
- Xử lý lỗi và phản hồi: Cung cấp ý kiến phản hồi hoặc thông báo lỗi rõ ràng cho người dùng nếu có vấn đề khi họ đăng xuất. Thông báo cho họ về mọi rủi ro bảo mật tiềm ẩn hoặc rò rỉ dữ liệu nếu quy trình đăng xuất không thành công.
- Những điểm cần cân nhắc về khả năng hỗ trợ tiếp cận: Đảm bảo rằng người dùng bị khuyết tật có thể dùng cơ chế đăng xuất, kể cả những người sử dụng công nghệ hỗ trợ như trình đọc màn hình hoặc thao tác bằng bàn phím.
- Khả năng tương thích trên nhiều trình duyệt: Kiểm tra chức năng đăng xuất trên các trình duyệt và thiết bị khác nhau để đảm bảo chức năng này hoạt động nhất quán và đáng tin cậy.
- Giám sát và cập nhật liên tục: Thường xuyên giám sát quá trình đăng xuất để phát hiện mọi lỗ hổng bảo mật hoặc lỗ hổng bảo mật tiềm ẩn. Triển khai các bản cập nhật và bản vá kịp thời để giải quyết mọi vấn đề đã xác định.
- Liên kết danh tính: Nếu người dùng đăng nhập bằng danh tính liên kết, hãy xem việc đăng xuất khỏi nhà cung cấp danh tính có được hỗ trợ và cần thiết hay không. Ngoài ra, nếu nhà cung cấp danh tính hỗ trợ tính năng tự động đăng nhập, đừng quên ngăn chặn tính năng này.
Việc nên làm
- Nếu bạn vô hiệu hoá một cookie trên máy chủ trong quy trình đăng xuất (hoặc các quy trình thu hồi quyền truy cập khác), hãy nhớ xoá cả cookie đó trên thiết bị của người dùng.
- Dọn dẹp mọi dữ liệu nhạy cảm mà bạn có thể đã lưu trữ trên thiết bị của người dùng: cookie, localStorage, sessionStorage, indexedDB, CacheStorage và bất kỳ kho dữ liệu cục bộ nào khác.
- Đảm bảo rằng mọi tài nguyên chứa dữ liệu nhạy cảm (cụ thể là tài liệu HTML) đều được trả về cùng với tiêu đề HTTP
Cache-control: no-store
để trình duyệt không lưu trữ những tài nguyên này trong bộ nhớ vĩnh viễn (ví dụ: trên ổ đĩa). Tương tự, các lệnh gọi XHR/fetch
trả về dữ liệu nhạy cảm cũng phải đặt tiêu đề HTTPCache-Control: no-store
để ngăn chặn mọi hoạt động lưu vào bộ nhớ đệm. - Đảm bảo rằng mọi thẻ đang mở trên thiết bị của người dùng đều đã được cập nhật, kèm theo việc thu hồi quyền truy cập phía máy chủ.
Dọn dẹp dữ liệu nhạy cảm khi bạn đăng xuất
Sau khi đăng xuất, hãy cân nhắc việc xoá dữ liệu nhạy cảm tạm thời và được lưu trữ cục bộ. Thực tế, việc xoá mọi thứ sẽ dẫn đến trải nghiệm người dùng kém hơn đáng kể vì người dùng này rất có thể quay lại và tập trung vào dữ liệu nhạy cảm. Ví dụ: nếu bạn muốn xoá tất cả dữ liệu được lưu trữ cục bộ, thì người dùng của bạn sẽ phải xác nhận lại lời nhắc về sự đồng ý đối với việc sử dụng cookie và thực hiện các quy trình khác như thể là ban đầu họ chưa từng truy cập vào trang web của bạn.
Cách xoá cookie
Trên phản hồi cho trang xác nhận trạng thái đã đăng xuất, hãy đính kèm tiêu đề HTTP Set-Cookie
để xoá mọi cookie có liên quan đến hoặc có chứa dữ liệu nhạy cảm. Đặt giá trị expires
thành một ngày trong quá khứ xa và đặt giá trị của cookie thành chuỗi trống để đo lường chính xác.
Set-Cookie: sensitivecookie1=; expires=Thu, 01 Jan 1970 00:00:00 GMT; secure
Set-Cookie: sensitivecookie2=; expires=Thu, 01 Jan 1970 00:00:00 GMT; secure
...
Tình huống không có kết nối mạng
Mặc dù phương pháp được mô tả ở trên là đủ cho các trường hợp sử dụng chung, nhưng phương pháp này sẽ không hoạt động nếu người dùng đang làm việc ngoại tuyến. Bạn có thể cân nhắc việc yêu cầu hai cookie để theo dõi trạng thái đăng nhập: một cookie bảo mật chỉ dành cho HTTPS và một cookie thông thường có thể truy cập qua JavaScript. Nếu người dùng của bạn đang cố đăng xuất khi không có kết nối mạng, thì bạn có thể xoá cookie JavaScript và tiếp tục các thao tác dọn dẹp khác, nếu có thể. Nếu có một trình chạy dịch vụ, bạn cũng nên tận dụng API tìm nạp trong nền để thử lại một yêu cầu xoá trạng thái trên máy chủ khi người dùng có kết nối mạng sau đó.
Cách giải phóng bộ nhớ
Trên phản hồi cho trang xác nhận trạng thái đăng xuất, hãy chú ý xoá dữ liệu nhạy cảm khỏi nhiều kho dữ liệu:
sessionStorage: Mặc dù bộ nhớ này bị xoá khi người dùng chấm dứt phiên truy cập với trang web của bạn, nhưng hãy cân nhắc chủ động xoá dữ liệu nhạy cảm khi người dùng đăng xuất, phòng trường hợp họ quên đóng tất cả các thẻ đang mở trên trang web của bạn.
// Remove sensitive data from sessionStorage
sessionStorage.removeItem('sensitiveSessionData1');
// ...
// Or if everything in sessionStorage is sensitive, clear it all
sessionStorage.clear();Các API localStorage, indexedDB, Cache/Service Worker: Khi người dùng đăng xuất, hãy dọn dẹp mọi dữ liệu nhạy cảm mà bạn có thể đã lưu trữ bằng các API này, miễn là dữ liệu đó sẽ vẫn tồn tại qua các phiên.
// Remove sensitive data from localStorage:
localStorage.removeItem('sensitiveData1');
// ...
// Or if everything in localStorage is sensitive, clear it all:
localStorage.clear();// Delete sensitive object stores in indexedDB:
const name = 'exampleDB';
const version = 1;
const request = indexedDB.open(name, version);
request.onsuccess = (event) => {
const db = request.result;
db.deleteObjectStore('sensitiveStore1');
db.deleteObjectStore('sensitiveStore2');
// ...
db.close();
}// Delete sensitive resources stored via the Cache API:
caches.open('cacheV1').then((cache) => {
await cache.delete("/personal/profile.png");
// ...
}
// Or better yet, clear a cache bucket that contains sensitive resources:
caches.delete('personalizedV1');
Cách xoá bộ nhớ đệm
- Bộ nhớ đệm HTTP: Miễn là bạn đặt
Cache-control: no-store
trên các tài nguyên có dữ liệu nhạy cảm, thì bộ nhớ đệm HTTP sẽ không giữ lại bất kỳ dữ liệu nhạy cảm nào. - Bộ nhớ đệm cho thao tác tiến/lùi: Tương tự như vậy, nếu bạn làm theo đề xuất về
Cache-control: no-store
và về việc xoá cookie nhạy cảm (ví dụ: cookie bảo mật chỉ dùng để xác thực qua HTTPS) khi người dùng đăng xuất, thì bạn không cần phải lo lắng về việc dữ liệu nhạy cảm sẽ bị giữ lại trong bộ nhớ đệm cho thao tác tiến/lùi. Trên thực tế, tính năng bộ nhớ đệm cho thao tác tiến/lùi sẽ loại bỏ các trang có cùng nguồn gốc được phân phát với tiêu đề HTTPCache-control: no-store
nếu phát hiện thấy một hoặc nhiều tín hiệu sau đây:- Một hoặc nhiều cookie an toàn chỉ dành cho HTTPS đã bị sửa đổi hoặc bị xoá.
- Một hoặc nhiều phản hồi cho các lệnh gọi XHR/
fetch
(do trang này cung cấp) đã bao gồm tiêu đề HTTPCache-control: no-store
.
Trải nghiệm nhất quán cho người dùng trên các thẻ
Người dùng có thể đã mở nhiều thẻ trên trang web của bạn trước khi quyết định đăng xuất. Khi đó, họ có thể đã quên mất các thẻ khác, hay thậm chí các cửa sổ trình duyệt khác. Tốt nhất là bạn nên tránh để người dùng đóng tất cả các thẻ và cửa sổ có liên quan. Thay vào đó, hãy thể hiện thái độ chủ động bằng cách đảm bảo rằng trạng thái đăng nhập của người dùng là nhất quán trên các thẻ.
Cách thực hiện
Để có trạng thái đăng nhập nhất quán trên các thẻ, hãy cân nhắc sử dụng kết hợp các sự kiện pageshow
/pagehide
và Broadcast Channel API.
Sự kiện
pageshow
: Sau khipageshow
duy trì, hãy kiểm tra trạng thái đăng nhập của người dùng và xoá dữ liệu nhạy cảm (hoặc thậm chí là toàn bộ trang) nếu người dùng không còn đăng nhập nữa. Xin lưu ý rằng sự kiệnpageshow
sẽ kích hoạt trước khi trang hiển thị lần đầu tiên khi được khôi phục từ thao tác điều hướng tiến/lùi. Điều này đảm bảo rằng chế độ kiểm tra trạng thái đăng nhập sẽ cho phép bạn đặt lại trang về trạng thái không nhạy cảm.window.addEventListener('pageshow', (event) => {
if (event.persisted && !document.cookie.match(/my-cookie)) {
// The user has logged out.
// Force a reload, or otherwise clear sensitive information right away.
body.innerHTML = '';
location.reload();
}
});API Kênh phát sóng: Sử dụng API này để thông báo các thay đổi về trạng thái đăng nhập trên các thẻ và cửa sổ. Nếu người dùng đã đăng xuất, hãy xoá tất cả dữ liệu nhạy cảm hoặc chuyển hướng đến một trang đăng xuất trên tất cả các thẻ và cửa sổ có dữ liệu nhạy cảm.
// Upon logout, broadcast new login state so that other tabs can clean up too:
const bc = new BroadcastChannel('login-state');
bc.postMessage('logged out');
// [...]
const bc = new BroadcastChannel('login-state');
bc.onMessage = (msgevt) => {
if (msgevt.data === 'logged out') {
// Clean up, reload or navigate to the sign-out page.
// ...
}
}
Kết luận
Bằng cách làm theo hướng dẫn trong tài liệu này, bạn có thể thiết kế một trải nghiệm người dùng đăng xuất hiệu quả, giúp ngăn chặn việc đăng xuất ngoài ý muốn và bảo vệ thông tin cá nhân của họ.