android - 何时用刷新 token 交换访问 token

标签 android ios concurrency oauth-2.0 network-programming

我理解使用 OAuth2 的流程是:

在短期访问 token 过期后(服务器返回 401),客户端必须使用刷新 token 请求一个新的访问 token 。

要在 iOS(使用 AFNetworking)或 Android(使用 Volley)应用程序中实现它,我想网络管理器必须能够检测到返回的 401 错误,然后将请求发送到身份验证服务器。

问题出在网络的并发使用上。考虑访问权限已过期的情况,应用程序发送 2 个请求:req1 和 100 毫秒后,req2。在时间轴上绘制,如下所示:

req1 --> 401 --> (refresh req) --> OK, new access and fresh tokens --> retry req1
  req2 --> 401 --> (refresh req) --> 403, wrong refresh token

最终结果是 req2 将失败,应用会因 403 错误将用户注销。

所以我的问题是

此实现是否朝着正确的方向发展?还是收到401后刷新不对?我是否应该在用户启动应用程序时刷新 token (以减慢应用程序启动速度为代价)

如何解决并发问题?

最佳答案

由于您有一个现有的 token 管理器,我会向其中添加一些额外的逻辑(用 Java 语言):

class TokenManager {

  private String accessToken;
  private CompletableFuture<String> accessTokenRefreshComletableFuture;

  public CompletableFuture<String> getAccessToken() {
    if (this.accessToken is expired) {
       // If refreshed accessToken is being requested
       CompletableFuture<String> runningRequestFuture = this.accessTokenRefreshComletableFuture;
       if (runningRequestFuture == null) {
          // For thread safety, this assignment should be synchronized (or made atomic)
          // with the previous reading
          this.accessTokenRefreshComletableFuture = new CompletableFuture<>();
          // Request a fresh access token.
          // When you get a new access token, set the this.accessTokenRefreshComletableFuture 
          // complete and remove its reference from the manager class.
       }
       return runningRequestFuture;
    }
    // Synchronous result
    return CompletableFuture.completedFuture(this.accessToken);
  }
}

管理器不会返回访问 token ,而是返回 CompletableFuture (JavaScript 中的 Promise - 异步结果)。如果需要刷新访问 token ,请首先检查 /token 端点请求是否已在运行。如果是,则返回它的 CompletableFuture

这样,您将始终拥有一个有效的访问 token 或一个等待新访问 token 的 CompletableFuture

关于android - 何时用刷新 token 交换访问 token ,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/54196823/

相关文章:

android - 如何在 Firebase (Android) 中实现 ondelete 级联

java - java.util.concurrent.BlockingQueue 的实现

c++ - std::atomic 和多核处理器

java - 在 Java 中使用 ThreadLocal 的良好实践

Android Studio 无法访问其他类中的函数

java - 对 libGDX 项目的外部 gradle 依赖

java - Android异常中的来电拦截

ios - og:url元标记是什么?

ios - 如何对项目内不同组的多个图像进行动画处理?

ios - 为 POST 请求使用辅助函数