我正在使用Flutter、GraphQL和带有NodeJS API的Firebase构建应用程序。在我的应用程序中,我实现了Firebase身份验证和令牌刷新,我的nodejs api对其进行了验证。我的令牌刷新间隔为3500秒(其中令牌有效期为3600秒(。然而,在某些情况下(我不知道为什么(,在我让应用程序打开半天后,我开始收到来自令牌验证的消息,我必须刷新令牌(不知道如何捕获它,因为在测试间隔刷新时效果很好(。。。
那么,在应用程序中刷新令牌最常见的方法是什么呢?也许应用程序会在不活动和刷新计时器停止时自动进行hybernate?如果是,那么我应该用什么事件来捕捉应用程序再次激活?
感谢
p.s.经过一些研究,我意识到令牌刷新间隔有什么问题——而手机处于活动状态,刷新间隔工作正常。如果我锁定手机屏幕时间间隔停止。再次打电话后,时间间隔从开始再次开始。这里主要的问题发生了-由于FB令牌的有效期为1小时,所以有99%的iser会打开他的手机屏幕,在他再次打开后,计时器将从头开始-但令牌将过期。。。
你知道在手机/应用程序再次激活后会触发哪些颤动事件吗?
任何OAuth客户端中的一条绝对黄金法则是实现以下行为:
- 如果您从API获得401
- 尝试获取新的访问令牌-仅一次
- 重试API调用-仅一次
我的一些示例Android代码可以做到这一点。
然而,无论使用何种类型的客户端或技术,该要求都是通用的。在我自己的应用程序中,我从不读取代币到期信息,只是让401发生。这是一个有弹性的解决方案,因为401的发生有很多原因。
我建议首先关注需求,其次关注技术
Firebase Auth将每小时或根据需要自动刷新用户的ID令牌。你不必为此编写任何代码。
Android、iOS和JS库都提供了一种方法来监听ID令牌的更改,但Flutter显然没有公开这个API。但是,您仍然可以定期调用getIdToken(false(来获取当前的ID令牌。只是不要坚持太久。
所以经过研究,我最终用两个步骤解决了这个问题。
-
使用以下代码初始化定期令牌刷新:
void _handleAuthStateChanged(FirebaseUser e) async { if (e == null) { _authentication = null; } else { /// Get token final firebaseToken = await e.getIdToken(refresh: true); /// Setup token refresh firebaseToken.expirationTime.asFuture(() async { var user = await FirebaseAuth.instance.currentUser(); _handleAuthStateChanged(user); }); extension DateTimeFutureX on DateTime { Future<T> asFuture<T>([FutureOr<T> Function() computation]) async { final difference = this.difference(DateTime.now()); return Future.delayed(difference, computation); } }
并在应用程序在main.dart 中恢复时重新蚀刻令牌
@override
Future<void> didChangeAppLifecycleState(AppLifecycleState state) async {
super.didChangeAppLifecycleState(state);
if (state == AppLifecycleState.resumed) {
await _authService.refreshToken();
}
}