Flutter接入Firebase时如何实现用户登录1小时后自动登出?
Flutter + Firebase 试用到期自动登出实现方案
客户端侧实现(即时触发)
这是最直接的实现方式,用户登录成功后启动倒计时,到期直接触发对应逻辑:
- 首先定义全局定时器变量,避免重复创建和内存泄漏
Timer? _trialTimer;
- 修改
enterTrial方法,新增倒计时逻辑
Future enterTrial() async { final UserCredential user = await Auth.instance.googleSignInMethod(); final User actualUser = user.user; try { //_trial is a collection for users in Trial Period await _trial.doc(actualUser.email).set({ "name": actualUser.displayName, "email": actualUser.email, "creationDate": FieldValue.serverTimestamp(), }); // 启动1小时倒计时 _trialTimer?.cancel(); // 先取消已有计时器避免重复触发 _trialTimer = Timer(const Duration(hours: 1), () async { await _handleTrialExpire(actualUser.email); }); } catch (e) { print(e); } } // 封装统一的试用到期处理逻辑 Future _handleTrialExpire(String? email) async { if (email == null) return; // 1. 登出当前账号 await Auth.instance.signOut(); // 2. 迁移数据到_expired集合 final trialDoc = await _trial.doc(email).get(); if (trialDoc.exists) { await _expired.doc(email).set(trialDoc.data()!); await _trial.doc(email).delete(); } // 此处可自定义弹窗提示用户试用已到期 }
- 补充前台唤醒校验逻辑,避免APP切后台后定时器被系统暂停导致计时不准
继承WidgetsBindingObserver监听APP生命周期,每次APP回到前台时直接校验试用时长:
@override void didChangeAppLifecycleState(AppLifecycleState state) { super.didChangeAppLifecycleState(state); if (state == AppLifecycleState.resumed) { _checkTrialValid(); } } Future _checkTrialValid() async { final currentUser = Auth.instance.currentUser; if (currentUser?.email == null) return; final trialDoc = await _trial.doc(currentUser!.email).get(); // 不在试用集合直接触发到期逻辑 if (!trialDoc.exists) { await _handleTrialExpire(currentUser.email); return; } final createTime = trialDoc.data()?['creationDate'] as Timestamp?; if (createTime == null) return; final diff = DateTime.now().difference(createTime.toDate()); // 试用时长超过1小时触发到期逻辑 if (diff.inHours >= 1) { await _handleTrialExpire(currentUser.email); } }
后端侧兜底实现(避免客户端逻辑被绕过)
客户端逻辑可能被用户修改本地时间、杀进程绕过,建议搭配Firebase云函数做定时校验兜底:
- 部署定时触发的云函数,每10分钟扫描一次_trial集合,批量迁移到期的试用用户数据
const functions = require("firebase-functions"); const admin = require("firebase-admin"); admin.initializeApp(); exports.cleanExpiredTrials = functions.pubsub.schedule('every 10 minutes').onRun(async (context) => { // 计算1小时前的时间戳 const oneHourAgo = admin.firestore.Timestamp.fromDate(new Date(Date.now() - 3600 * 1000)); // 查出所有到期的试用用户 const expiredTrials = await admin.firestore().collection('_trial').where('creationDate', '<=', oneHourAgo).get(); // 批量操作提高执行性能 const batch = admin.firestore().batch(); expiredTrials.forEach(doc => { batch.set(admin.firestore().collection('_expired').doc(doc.id), doc.data()); batch.delete(doc.ref); }); await batch.commit(); return null; });
- 新增APP冷启动校验逻辑,每次打开APP先校验当前登录用户是否在试用集合,不在则直接登出
内容的提问来源于stack exchange,提问作者Martin Wittick
相关产品推荐
相关产品推荐

