Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/ios/101.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Android 何时将访问令牌与刷新令牌交换_Android_Ios_Concurrency_Oauth 2.0_Network Programming - Fatal编程技术网

Android 何时将访问令牌与刷新令牌交换

Android 何时将访问令牌与刷新令牌交换,android,ios,concurrency,oauth-2.0,network-programming,Android,Ios,Concurrency,Oauth 2.0,Network Programming,我了解使用OAuth2的流程是: 在短期访问令牌到期后,服务器返回401,客户端必须使用刷新令牌请求一个新的令牌 要在iOS和AFNetworking或Android和Volley应用程序中实现它,我认为网络管理器必须能够检测返回的401错误,然后将请求发送到auth服务器 问题在于网络的并发使用。考虑访问已经过期的情况,应用程序发送2个请求:Req1和100MS之后,Req2。在时间轴上绘制,如下所示: req1 --> 401 --> (refresh req) --> O

我了解使用OAuth2的流程是:

在短期访问令牌到期后,服务器返回401,客户端必须使用刷新令牌请求一个新的令牌

要在iOS和AFNetworking或Android和Volley应用程序中实现它,我认为网络管理器必须能够检测返回的401错误,然后将请求发送到auth服务器

问题在于网络的并发使用。考虑访问已经过期的情况,应用程序发送2个请求:Req1和100MS之后,Req2。在时间轴上绘制,如下所示:

req1 --> 401 --> (refresh req) --> OK, new access and fresh tokens --> retry req1
  req2 --> 401 --> (refresh req) --> 403, wrong refresh token
最终结果是req2将失败,并且由于403错误,应用程序将用户注销

所以我的问题是

这一实施是否朝着正确的方向发展?或者在收到401后刷新是错误的?当用户启动应用程序时,我是否应该以减慢应用程序启动速度为代价来刷新令牌


如何解决并发问题?

既然您有一个现有的令牌管理器,我将在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);
  }
}
管理器不返回访问令牌,而是返回JavaScript异步结果中的承诺。如果需要刷新访问令牌,请首先检查/token端点请求是否已在运行。如果是,返回它的完整未来


这样,您将始终拥有一个有效的访问令牌或一个完整的未来等待新的访问令牌。

您在android中使用哪个库调用api???@ChandrakantDvivedi我在使用Volley我在使用okHttp,其中提供了拦截器,您可以在请求和响应之间进行拦截。Volley也可以这样做,那么问题是如何交换数据token@Siyu您是否已经有一些令牌管理器实现,可用于连续请求,但在并行请求时可能会失败?因此,我们的想法是在发送任何请求之前检查令牌?是的,我认为在发送之前检查它是很好的-它更快,并且可以避免太多被禁止的请求击中服务器。但是,如果您从资源服务器获得HTTP 403,您应该使用刷新的访问令牌重试。好的,但是如果我获得了403,如何避免遇到我在文章中描述的场景?对不起,我是指HTTP 401-然后您将获得刷新的访问令牌。您不应该得到HTTP 403-req1将要求刷新令牌并等待它返回,req2将检测到只是等待刷新的令牌。然后他们都会使用相同的有效访问令牌。对不起,我对此有点固执,但我如何才能检测到req1正在请求一个新令牌并阻止req2?