Oauth2;如何解决多个异步 api 调用期间 AccessToken 过期的问题,同时进行?

Posted

技术标签:

【中文标题】Oauth2;如何解决多个异步 api 调用期间 AccessToken 过期的问题,同时进行?【英文标题】:Oauth2; How to solve the issue with expired AccessToken during multiple async api calls , made concurrently? 【发布时间】:2015-08-10 23:40:21 【问题描述】:

我在我的应用程序中使用 Spring Security Oauth2 作为安全层。一切运行良好,直到同时出现异步调用。

谁能告诉我如何处理下一个案例: 1.客户端的accessToken已经过期。 2. 客户端对我的 api 进行两次并发异步 api 调用(例如:Thread1、Thread2)。 3. Thread1 在 Thread2 之前收到一个错误:“accessToken expired”。 4. 通过使用refreshToken Thread1 接收到一个新的accessToken = qqqqq。 5. Thread2 在 Thread1 使用新的 accessToken = qqqqq 对服务器进行新调用之前收到错误:“accessToken expired”。 6. 通过使用 refreshToken Thread2 接收到一个新的 accessToken = wwwww 并删除 accessToken = qqqqq 。 7. 在这里,Thread1 使用 accessToken = qqqqq 调用服务器,该服务器未激活。 8. 理论上,通过使彼此无效来循环两个线程是完全可能的。

如果有任何帮助,我将不胜感激,谢谢。

【问题讨论】:

【参考方案1】:

如果您已控制客户端,则可以将版本号附加到访问令牌 - 如果线程尝试使用旧版本号刷新访问令牌,则返回当前(最近刷新的)访问令牌.

public class AccessToken 
  private int currentVersion;
  private String accessToken;

  private static AccessToken currentToken;

  public static synchronized AccessToken refresh(AccessToken token) 
    if(token.currentVersion == currentToken.currentVersion) 
      AccessToken newToken = // refresh token
      newToken.currentVersion = currentToken.currentVersion + 1;
      currentToken = newToken;
    
    return currentToken;
  

如果您对客户端没有任何控制权和/或希望修复此服务器端,那么有几个选项是:

    允许客户端每个线程使用一个访问令牌,而不是要求它们跨线程共享一个全局访问令牌。 禁止每隔 5 秒刷新一次以上的访问令牌。这样,即使客户端遇到刷新循环,他们也应该能够取得一些进展。 公开一个仅在提供正确的当前令牌时才刷新令牌的方法,以便客户端可以有条件地更新其访问令牌(您仍然需要公开当前方法以绝对刷新令牌以防客户端忘记旧的访问令牌)。

【讨论】:

非常感谢。我可以控制客户端,所以我将使用“accessToken”版本。再次感谢您。 我的 Java 生锈了,但在示例代码中仍然存在竞争条件,对吗?两个线程可能会看到令牌是当前版本,然后尝试进行刷新,其中一个不确定地覆盖另一个。 你有服务器端第二点的代码示例吗?

以上是关于Oauth2;如何解决多个异步 api 调用期间 AccessToken 过期的问题,同时进行?的主要内容,如果未能解决你的问题,请参考以下文章

私有Blogger API调用没有oauth2

如何在 .net Core API 项目中跨多个线程限制对 HttpClient 的所有传出异步调用

如何在异步函数中处理多个等待

使用Dapper.NET异步API时如何尊重CommandTimeout

对 api 服务器的多个异步请求(即发即弃)

如果两个 API 使用不同的身份提供者,一个 API 将如何使用 oauth2 调用另一个 API?