Firebase Auth 用户被禁用或删除时如何实现自动登出?
核心问题原因
- Firebase 客户端SDK的登录状态完全基于本地缓存的身份令牌维持,默认身份令牌的有效期为1小时
- 当你在控制台删除、禁用用户时,本地不会主动感知服务端的状态变更,只要本地缓存的令牌还在有效期,客户端就会默认用户处于合法登录状态,不会触发
onAuthStateChanged的回调。 - 你原代码中只在组件挂载时单次调用了
currentUser.reload(),没有持续的服务端状态校验逻辑,自然无法在控制台操作后同步状态。同时原代码存在逻辑时序问题:把unsubscribe的定义写在回调内部,首次进入回调时还无法拿到完整的取消监听实例,后续调用会失效。
正确实现方案
重构监听逻辑,和SDK自带的令牌自动刷新机制绑定,不需要额外写定时器轮询
完整可运行的代码参考:// 组件作用域内定义取消监听的变量,方便后续清理 let authUnsubscribe = null; async onAuthStateChanged() { // 页面挂载时先做一次全量的服务端状态校验 try { if (firebase.auth().currentUser) { // 强制同步服务端最新的用户状态,被删除/禁用的用户会在此处直接抛出错误 await firebase.auth().currentUser.reload(); } } catch (e) { this.forceLogout(); return; } // 初始化认证状态监听 authUnsubscribe = firebase.auth().onAuthStateChanged(async (currentUser) => { if (currentUser) { // 强制开启令牌的自动校验刷新,SDK会在令牌接近过期时主动和服务端校验有效性 currentUser.getIdToken(true); // 监听令牌的变更/失效事件 currentUser.onTokenRefresh(() => { // 令牌刷新成功代表用户状态合法,无需额外处理 // 如果刷新失败(用户被禁用/删除),SDK会自动触发onAuthStateChanged的空值回调 }); } else { // 用户已登出/状态失效的逻辑 authUnsubscribe?.(); this.forceLogout(); } }) } // 抽离统一的强制登出逻辑 forceLogout() { this.props.navigation.navigate('login'); } // 组件卸载时清理监听,避免内存泄漏 componentWillUnmount() { authUnsubscribe?.(); }关键逻辑说明
- 只要用户被控制台删除/禁用,当SDK主动去服务端刷新令牌时,服务端会直接返回身份无效,SDK会自动清空本地的缓存用户信息,触发
onAuthStateChanged的空值回调,走登出流程 - 整个校验过程不需要手动写定时器,完全复用SDK自带的令牌刷新机制,既不会额外消耗SDK调用配额,也能做到令牌有效期内自动同步服务端状态
- 首次进入页面时的
currentUser.reload()会立刻触发一次全量校验,哪怕令牌还在有效期,也能立刻感知到用户被禁用/删除的状态。
- 只要用户被控制台删除/禁用,当SDK主动去服务端刷新令牌时,服务端会直接返回身份无效,SDK会自动清空本地的缓存用户信息,触发
常见踩坑提醒
- 不要在回调内部给
unsubscribe变量赋值后立刻调用,会出现闭包引用的时序错误,必须把变量提到组件的外层作用域定义 - 不要自己写
setInterval定时调用用户状态接口,会造成不必要的流量消耗,也可能触发SDK的调用频率限制 - 组件卸载时一定要记得调用
authUnsubscribe()取消监听,否则页面多次切换后会出现内存泄漏、重复触发回调的问题。
内容的提问来源于stack exchange,提问作者showtime
相关产品推荐
相关产品推荐

