Đăng xuất
Khi người dùng đăng xuất khỏi một trang web, họ đang cho biết mong muốn thoát hoàn toàn khỏi trải nghiệm được cá nhân hoá. Do đó, điều quan trọng là phải tuân thủ mô hình tinh thần của người dùng càng chặt chẽ càng tốt. Ví dụ: trải nghiệm đăng xuất phù hợp cũng phải tính đến mọi thẻ mà người dùng có thể đã mở trước khi quyết định đăng xuất.
Chìa khoá để mang lại trải nghiệm đăng xuất tuyệt vời có thể được tóm tắt là tính 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 đưa ra lời khuyên cụ thể về những điều cần chú ý và cách mang lại trải nghiệm đăng xuất tốt.
Những điểm cần cân nhắc chính
Khi triển khai chức năng đăng xuất trên trang web, hãy chú ý đến những khía cạnh sau để đảm bảo quy trình đăng xuất diễn ra suôn sẻ, an toàn và trực quan:
- Trải nghiệm người dùng rõ ràng và nhất quán khi đăng xuất: Cung cấp nút hoặc đường liên kết đăng xuất rõ ràng và xuất hiện nhất quán, dễ dàng xác định và truy cập được trên toàn bộ trang web. Tránh sử dụng nhãn mơ hồ hoặc ẩn chức năng đăng xuất trong các trình đơn, trang con hoặ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 cân nhắc lại xem họ có thực sự cần đăng xuất hay không, ví dụ: nếu họ cẩn thận khoá thiết bị 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ở một số 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 an toàn 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 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 phiên hoạt động nhạy cảm của người dùng, cookie hoặc tệp tạm thời liên kết với phiên hoạt động của người dùng. Điều này 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 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 quay lại/chuyển tiếp.
- Xử lý lỗi và phản hồi: Cung cấp thông báo lỗi hoặc phản hồ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 hoặc rò rỉ dữ liệu tiềm ẩn nếu quy trình đăng xuất không thành công.
- Những điều cần cân nhắc về hỗ trợ tiếp cận: Đảm bảo rằng người dùng khuyết tật, bao gồm 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, có thể sử dụng cơ chế đăng xuất.
- Khả năng tương thích trên nhiều trình duyệt: Kiểm thử chức năng đăng xuất trên nhiều trình duyệt và thiết bị để đảm bảo chức năng này hoạt động nhất quán và đáng tin cậy.
- Thường xuyên theo dõi và cập nhật: Thường xuyên theo dõi quy trình đăng xuất để phát hiện mọi lỗ hổng bảo mật hoặc sơ hở 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 được liên kết, hãy xem liệu 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.
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á 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à mọi kho dữ liệu cục bộ khác.
- Đảm bảo rằng mọi tài nguyên chứa dữ liệu nhạy cảm (đặc biệt là tài liệu HTML) đều được trả về bằng tiêu đề HTTP
Cache-control: no-store
để trình duyệt không lưu trữ các tài nguyên này trong bộ nhớ cố định (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 việc 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 thông tin về việc thu hồi quyền truy cập phía máy chủ.
Xoá dữ liệu nhạy cảm khi đăng xuất
Khi đăng xuất, hãy cân nhắc xoá dữ liệu nhạy cảm tạm thời và dữ liệu nhạy cảm được lưu trữ cục bộ. Việc tập trung vào dữ liệu nhạy cảm là do việc xoá mọi thứ sẽ dẫn đến trải nghiệm người dùng tệ hơn đáng kể vì người dùng này rất có thể sẽ quay lại. Ví dụ: nếu bạn xoá tất cả dữ liệu được lưu trữ cục bộ, thì người dùng sẽ phải xác nhận lại lời nhắc đồng ý sử dụng cookie và trải qua các quy trình khác như thể 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 liên quan đến hoặ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 một chuỗi trống để đo lường hiệu quả.
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 ngoại tuyến
Mặc dù phương pháp 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 nên 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 được qua JavaScript. Nếu người dùng đang cố đăng xuất khi không có mạng, 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ó worker dịch vụ, bạn cũng nên tận dụng Background Fetch API (API Tìm nạp ở chế độ nền) để thử lại 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 dọn dẹp bộ nhớ
Trên phản hồi cho trang xác nhận trạng thái đã đăng xuất, hãy cẩn thận xoá dữ liệu nhạy cảm khỏi nhiều kho dữ liệu:
sessionStorage: Mặc dù dữ liệu này sẽ bị xoá khi người dùng chấm dứt phiên hoạt động trên trang web của bạn, nhưng bạn nên chủ động dọn dẹp 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ẻ đã 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();
localStorage, indexedDB, Bộ nhớ đệm/Trình chạy dịch vụ API: Khi người dùng đăng xuất, hãy xoá mọi dữ liệu nhạy cảm mà bạn có thể đã lưu trữ bằng các API này, vì dữ liệu đó sẽ tồn tại trong 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 dọn dẹp 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, 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 quay lại/chuyển tiếp: Tương tự, nếu đã làm theo các đề xuất về
Cache-control: no-store
và về việc xoá cookie nhạy cảm (ví dụ: cookie chỉ dành cho HTTPS an toàn liên quan đến việc xác thực) 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 bị giữ lại trong bộ nhớ đệm quay lại/chuyển tiếp. Thật vậy, tính năng bộ nhớ đệm cho thao tác tiến/lùi sẽ loại bỏ các trang cùng nguồn gốc được phân phát bằng tiêu đề HTTPCache-control: no-store
nếu tính năng này quan sát thấy một hoặc nhiều tín hiệu sau:- Một hoặc nhiều cookie bảo mật chỉ dành cho HTTPS đã bị sửa đổi hoặc xoá.
- Một hoặc nhiều phản hồi cho các lệnh gọi XHR/
fetch
do trang đưa ra, 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ẻ cho trang web của bạn trước khi quyết định đăng xuất. Khi đó, họ có thể đã quên các thẻ khác hoặc thậm chí là các cửa sổ trình duyệt khác. Tốt nhất là bạn không nên dựa vào người dùng để đóng tất cả các thẻ và cửa sổ có liên quan. Thay vào đó, hãy chủ động đảm bảo trạng thái đăng nhập của người dùng nhất quán trên các thẻ.
Cách thực hiện
Để đạt đượ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
: Khipageshow
được 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. Xin lưu ý rằng sự kiệnpageshow
sẽ kích hoạt trước khi trang được hiển thị lần đầu tiên sau khi khôi phục từ thao tác di chuyển lui/tiến, đảm bảo rằng việc 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(); } });
Broadcast Channel API: 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 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ế trải nghiệm đăng xuất tuyệt vời cho người dùng, 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 người dùng.