okhttp OAuth拦截器

时间:2015-02-27 13:12:27

标签: java multithreading oauth okhttp

我尝试为okhttp实现oAuth拦截器,但我无法获得该问题的完整解决方案。我目前的解决方案如下:

public abstract class AuthInterceptor implements Interceptor {

  /**
   * We are super lazy and use this lock object, instead of Lock and Condition
   */
  private Object lock = new Object();
  private AtomicBoolean authenticated = new AtomicBoolean(false);

  @Override public Response intercept(Chain chain) throws IOException {

    final Request request = chain.request();
    Response response = chain.proceed(request);

    if (response.code() != 401 ) {
      return response; // should not intercept, we are done;
    }

    // response code was 401
    authenticated.set(false);

    synchronized (lock) {

      // TODO pause okhttp executore service

      if (!authenticated.get()) {
        if (doAuthentication()) {
          authenticated.set(true);
        } else {
          // authentication failed, so forward original response (401)
          return response;
        }

        // TODO resume okhttp executor service
      }
    }

    // Redo the request, by adding the fresh access token
    return redoRequest(chain);
  }

  /**
   * Gets a fresh auth token from server.
   * Returns true if a new valid auth token was retrieved from server
   */
  protected abstract boolean doAuthentication();

  /**
   * re-execute the request by setting the new (valid) auth token
   */
  protected abstract redoRequest(Chain chain);
}

这个想法是只允许一个具有401响应的线程(或者你可以说一个请求)通过调用doAuthentication()来刷新身份验证令牌。所有其他线程应该在synchronized块前面等待。执行doAuthentication()的线程离开synchronizedauthenticated = true后,其他线程不应再次调用doAuthentication()

但我看到一个问题:理论上,以下场景中有两个线程的线程是可能的:

  1. 主题1输入syncronized
  2. 线程1执行doAuthentication()并获得一个新的(有效)身份验证令牌。
  3. 主题1设置authenticated = true
  4. 另一个帖子2会覆盖authenticated.set(false);synchronized阻止之前)
  5. 线程1离开同步块 - >新(有效)身份验证令牌
  6. 线程2进入同步块。由于authenticated已被覆盖,它会再次执行doAuthentication()不应该执行,因为几毫秒之前检索到的身份验证令牌应该使用Thread1。
  7. 我认为在实践中这不会经常发生。但是,你们中谁都看到了解决这个问题的完美解决方案吗?我还考虑了在获取新的身份验证令牌时暂停/ okhttps ExecutorService以最大限度地降低在这种情况下挣扎的风险。

0 个答案:

没有答案