当用户从网站退出账号时,他们是在表明自己需要完全退出个性化用户体验。因此,尽可能贴近用户的心理模型非常重要。例如,适当的退出体验还应考虑到用户在决定退出之前可能已打开的任何标签页。
要提供出色的退出体验,关键在于确保用户体验在视觉和状态方面保持一致。本指南提供了有关应注意哪些事项以及如何实现良好的退出体验的具体建议。
主要注意事项
在网站上实现退出功能时,请注意以下方面,以确保退出流程顺畅、安全且直观:
- 清晰且一致的退出登录用户体验:提供清晰且始终可见的退出登录按钮或链接,确保用户可以在整个网站中轻松识别和访问。避免使用含义模糊的标签,或将退出功能隐藏在不显眼的菜单、子网页或其他不直观的位置。
- 确认提示:在完成退出流程之前实现确认提示。这样一来,有助于防止用户意外退出登录,并允许用户重新考虑是否真的需要退出登录,例如,如果用户认真地使用强密码或其他身份验证机制锁定设备,则无需退出登录。
- 处理多个标签页:如果用户在不同标签页中打开了同一网站的多个网页,请确保从一个标签页中退出登录后,该网站的所有其他打开的标签页也会随之更新。
- 重定向到安全的着陆页:成功退出登录后,将用户重定向到安全的着陆页,该页面应明确指示用户已不再处于登录状态。避免将用户重定向到包含任何个性化信息的网页。同样,确保其他标签页也不再显示已登录状态。此外,请确保您不会构建攻击者可利用的开放式重定向。
- 会话清理:用户退出登录后,完全移除与用户会话关联的任何敏感用户会话数据、Cookie 或临时文件。这样可以防止未经授权的用户访问用户的信息或账号活动,还可以防止浏览器从其各种缓存(尤其是后退/前进缓存)中恢复包含敏感信息的网页。
- 错误处理和反馈:如果用户在退出时遇到任何问题,请向其提供清晰的错误消息或反馈。如果退出流程失败,请告知他们任何潜在的安全风险或数据泄露情况。
- 无障碍功能注意事项:确保退出机制可供残障用户使用,包括使用屏幕阅读器或键盘导航等辅助技术的用户。
- 跨浏览器兼容性:在不同浏览器和设备上测试退出功能,确保该功能始终可靠地运行。
- 持续监控和更新:定期监控退出流程,以发现任何潜在的漏洞或安全漏洞。及时实施更新和补丁,以解决发现的任何问题。
- 身份联合:如果用户使用联合身份登录,请查看是否支持并需要从身份提供方退出登录。此外,如果身份提供方支持自动登录,请务必阻止它。
DOs
- 如果您在服务器上使 Cookie 失效(作为退出流程或其他访问权限撤消流程的一部分),请务必同时删除用户设备上的相应 Cookie。
- 清理您可能存储在用户设备上的任何敏感数据:Cookie、localStorage、sessionStorage、indexedDB、CacheStorage 和任何其他本地数据存储区。
- 确保返回的任何包含敏感数据的资源(尤其是 HTML 文档)都带有
Cache-control: no-store
HTTP 标头,以便浏览器不会将这些资源存储在永久存储空间(例如磁盘)中。同样,返回敏感数据的 XHR/fetch
调用也应设置Cache-Control: no-store
HTTP 标头,以防止任何缓存。 - 确保用户设备上打开的所有标签页都与服务器端撤消的访问权限保持同步。
在退出账号时清理敏感数据
退出账号后,请考虑清除临时存储的敏感数据和本地存储的敏感数据。之所以侧重于敏感数据,是因为清除所有数据会导致用户体验显著变差,而用户很可能会再次访问。例如,如果您清除所有本地存储的数据,那么您的用户将不得不重新确认 Cookie 意见征求提示,并像从未访问过您的网站一样完成其他流程。
如何清理 Cookie
在确认已退出账号状态的网页的响应中,附加 Set-Cookie
HTTP 标头以清除与敏感数据相关或包含敏感数据的所有 Cookie。将 expires
值设置为遥远的过去日期,并将 Cookie 的值设置为空字符串,以确保万无一失。
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
...
离线场景
虽然上述方法足以应对一般使用情形,但如果用户处于离线状态,则无法使用此方法。您不妨考虑要求使用两个 Cookie 来跟踪登录状态:一个安全的仅限 HTTPS 的 Cookie,以及一个可通过 JavaScript 访问的常规 Cookie。如果用户尝试在离线状态下退出登录,您可以清除 JavaScript Cookie,并尽可能继续执行其他清理操作。如果您有服务工作器,可能还想利用 Background Fetch API 在用户稍后上线时重试请求,以清除服务器上的状态。
如何清理存储空间
在确认已退出账号状态的网页的响应中,请务必清理各种数据存储区中的敏感数据:
sessionStorage:虽然当用户结束与您网站的会话时,系统会清除此存储空间,但为了防止用户忘记关闭在您网站上打开的所有标签页,请考虑在用户退出账号时主动清理敏感数据。
// Remove sensitive data from sessionStorage sessionStorage.removeItem('sensitiveSessionData1'); // ... // Or if everything in sessionStorage is sensitive, clear it all sessionStorage.clear();
localStorage、indexedDB、Cache/Service Worker API:当用户退出账号时,请清理您可能使用这些 API 存储的任何敏感数据,因为此类数据会在会话之间保持不变。
// 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 with 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');
如何清理缓存
- HTTP 缓存:只要您在包含敏感数据的资源上设置
Cache-control: no-store
,HTTP 缓存就不会保留任何敏感内容。 - 后退/前进缓存:同样,如果您遵循了有关
Cache-control: no-store
的建议,并在用户退出时清除了敏感 Cookie(例如与身份验证相关的仅限 HTTPS 的安全 Cookie),则无需担心敏感数据保留在后退/前进缓存中。实际上,如果往返缓存功能观察到以下一个或多个信号,就会逐出通过Cache-control: no-store
HTTP 标头提供的同源网页:- 一个或多个仅限 HTTPS 的安全 Cookie 已被修改或删除。
- 网页发出的 XHR/
fetch
调用的一项或多项响应中包含Cache-control: no-store
HTTP 标头。
在不同标签页中保持一致的用户体验
用户可能在决定退出之前打开了您网站的多个标签页。到那时,他们可能已经忘记了其他标签页,甚至其他浏览器窗口。最好避免依赖用户关闭所有相关标签页和窗口。相反,您应采取积极主动的措施,确保用户在各个标签页中的登录状态保持一致。
操作方法
如需在各个标签页中实现一致的登录状态,请考虑结合使用 pageshow
/pagehide
事件和 Broadcast Channel API。
pageshow
事件:在持久性pageshow
上,检查用户的登录状态,如果用户不再处于登录状态,则清除敏感数据(甚至整个页面)。从往返导航恢复后,pageshow
事件将在首次渲染网页之前触发,以便您的登录状态检查功能将网页重置为非敏感状态。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:使用此 API 可在标签页和窗口之间传递登录状态更改。如果用户已退出登录,请清除所有敏感数据,或者将所有包含敏感数据的标签页和窗口重定向到退出登录页面。
// 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. // ... } }
总结
按照本文档中的指南操作,您将能够设计出色的退出登录用户体验,防止意外退出登录,并保护用户的个人信息。