When to exchange access token with refresh token
我理解使用 OAuth2 的流程是:
在短期访问令牌过期后(服务器返回 401),客户端必须使用刷新令牌请求新的。
要在 iOS(使用 AFNetworking)或 Android(使用 Volley)应用程序中实现它,我想网络管理器必须能够检测返回的 401 错误,然后向身份验证服务器发送请求。
问题在于网络的并发使用。考虑访问已过期的场景,应用程序发送 2 个请求:req1 和 100 毫秒后,req2。绘制在时间轴上,如下所示:
1 2 | req1 --> 401 --> (refresh req) --> OK, new access and fresh tokens --> retry req1 req2 --> 401 --> (refresh req) --> 403, wrong refresh token |
最终的结果是req2会失败,应用会因为403错误退出用户。
所以我的问题是
这个实现是否朝着正确的方向发展?还是收到401后刷新不对?我是否应该在用户启动应用程序时刷新令牌(以减慢应用程序启动为代价)
如何解决并发问题?
由于您有一个现有的令牌管理器,我会在其中添加一些额外的逻辑(在 Java 中):
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 | 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); } } |
管理器不返回访问令牌,而是返回 CompletableFuture(JavaScript 中的 Promise - 异步结果)。如果需要刷新访问令牌,请先检查
这样,您将始终拥有一个有效的访问令牌或单个