请求重试最佳实践

Request retry best practices

我正在使用 Flutter、GraphQL 和 Firebase 以及 NodeJS 构建应用程序 API。 在我的应用程序中,我实现了 Firebase 身份验证和令牌刷新,我的 nodejs api 对其进行了验证。 我的令牌刷新间隔为 3500 秒(其中令牌的有效期为 3600 秒)。但是在某些情况下(我不知道为什么)在我将应用程序打开半天后,我开始收到来自令牌验证的消息,我必须刷新令牌(不知道如何捕获它,因为在测试间隔刷新时只是工作很好)...

那么在应用程序中刷新令牌最常见的方式是什么?也许应用程序会在非活动状态和刷新计时器停止时自动休眠?如果是 - 那么我应该使用什么事件来捕获应用程序再次激活?

谢谢

p.s。经过一些研究,我意识到令牌刷新间隔有什么问题 - 而 phone 是活动刷新间隔工作正常。如果我锁定 phones 屏幕时间间隔停止。在 oepning phone 之后,时间间隔再次从 BEGINNING 开始。这里出现了主要问题——因为 FB 令牌的有效期为 1 小时,所以有 99% 的人会打开他的 phone 屏幕,并且在他再次打开它之后,计时器将从头开始 - 但令牌将过期.. .

您知道 phone/应用程序再次激活后触发的任何 flutter 事件吗?

Firebase Auth 将每小时或根据需要自动刷新用户的 ID 令牌。您不必为此编写任何代码。

Android、iOS、JS库都提供了监听ID token变化的方法,但Flutter显然没有暴露这个API。但是,您仍然可以定期调用 getIdToken(false) 来获取当前 ID 令牌。只是不要坚持太久。

所以经过研究,我最终用 2 个步骤解决了它。

  1. 使用此代码初始化定期令牌刷新:

    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);
     }
    }
    
  1. 并在 main.dart

    中恢复应用程序时重新获取令牌
    @override
    Future<void> didChangeAppLifecycleState(AppLifecycleState state) async {
         super.didChangeAppLifecycleState(state);
         if (state == AppLifecycleState.resumed) {
             await _authService.refreshToken();
         }
     }
    

任何 OAuth 客户端的绝对黄金法则是实现以下行为:

  • 如果您从 API
  • 收到 401
  • 尝试获取新的访问令牌 - 仅一次
  • 重试 API 呼叫 - 仅一次

Some sample Android code of mine that does this.

但无论使用何种客户端类型或技术,该要求都是通用的。在我自己的应用程序中,我从不读取令牌过期时间,只是让 401 发生。这是一个有弹性的解决方案,因为 401 的发生可能有多种原因。

我建议首先关注需求,其次关注技术