【问题标题】:Request retry best practices请求重试最佳实践
【发布时间】:2020-11-20 16:27:50
【问题描述】:

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

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

谢谢

附言经过一些研究,我意识到令牌刷新间隔有什么问题 - 当手机处于活动状态时,刷新间隔工作正常。如果我锁定手机屏幕时间间隔停止。再次打开电话后,时间间隔从头开始。这里出现了主要问题 - 因为 FB 令牌的有效期为 1 小时,所以 99% 的 iser 会转动他的手机屏幕,在他再次转动手机屏幕后,计时器将从头开始 - 但令牌将过期......

您知道手机/应用再次激活后触发的任何颤振事件吗?

【问题讨论】:

  • 请编辑问题以限制自己在每个帖子中只回答一个问题,否则它可能会因为“需要关注”而关闭。我会在这里回答你的第一个问题,我建议你单独问第二个问题。

标签: android flutter firebase-authentication graphql refresh-token


【解决方案1】:

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

  • 如果您从 API 获得 401
  • 尝试获取新的访问令牌 - 仅一次
  • 重试 API 调用 - 仅一次

Some sample Android code of mine that does this.

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

我建议首先关注需求,然后关注技术

【讨论】:

    【解决方案2】:

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

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

    【讨论】:

    • 所以基本上在应用程序打开时我必须获取新令牌并开始收听 onAuthStateChanged (dart 库仍然使用此流)它传递给我 FirebaseUser 作为结果我应该做 FirebaseAuth.instance.onAuthStateChanged.listen ((event) async { token = (await event.getIdToken()).token; });
    • 抱歉,我编辑了我的问题,因为我没有看到 Flutter 公开了 ID 令牌更改侦听器。您可以改为定期调用 getIdToken。
    • 您需要在需要时获取 ID 令牌,以便确定您有一个新的令牌。
    • 如您所见,它暴露了 AuthStateChanged - 所以刷新令牌时不会触发它?为什么你将 false 传递给 getIdToken? false 表示不刷新 - 但我想像我原来的问题一样刷新它。
    • 我认为 onAuthStateChanged 应该做同样的事情——“添加一个观察者来观察登录用户的 ID 令牌的变化,包括登录、注销和令牌刷新事件。这个方法有与 firebase.auth.Auth.onAuthStateChanged 在 4.0.0 之前的行为相同。”
    【解决方案3】:

    所以经过研究,我最终通过 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();
           }
       }
      

    【讨论】:

      猜你喜欢
      • 2021-05-07
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2018-02-22
      • 2020-04-19
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多