使用Retrofit,RxJava和Observable.share重新验证?

时间:2017-03-14 09:22:03

标签: java android authentication retrofit rx-java

前提:

  1. 我们使用3小时后过期的会话令牌
  2. 我必须使用名为auth
  3. 的特殊电话
  4. 目前,当会话令牌过期时,我们不会抢先刷新它,而是尝试调用,如果该调用返回401-UNAUTHORIZED,我们会调用auth并重试该调用。它有效,但它不是很好
  5. 我们正在使用Retrofit1和RxJava1(目前无法更新)
  6. 我想以这样的方式更改它,我会在调用之前检查是否需要刷新令牌。

    我希望通过链接Observable并在调用之间共享Auth-Observable来实现这一点

    这样想:

    1. 检查SessionToken是否即将过期或已过期
    2. 启动Auth-Call(返回Observable)
    3. 将我的电话连接到Auth-Call Observable
    4. 当另一个呼叫发生并且看到sessiontoken接近到期时,检查是否有正在进行的Auth-Call。如果有,请将新呼叫链接到Auth-Call
    5. 第一个问题:这实际上是一个明智的想法吗? 第二个问题:这实际上是否可行? 第三个问题:我该怎么做?

3 个答案:

答案 0 :(得分:3)

这方面的诀窍是使用Singleton Observable

Observable<AuthResponse> mAuthSingleton = retrofit.authenticate()
    .doOnNext( response -> saveSessionToken(response.getSessionToken())
    .share();


Observable<AuthResponse> getAuthCallWhenNecessary(){
    if(sessionToken == null ||sessionToken.isAboutToExpire())
        return mAuthSingleton;
    else
        return Observable.just(new AuthResponse());
}

Observable<WhateverResponse> getWhatever(){
    return getAuthCallWhenNecessary().flatMap(response -> retrofit.getWhatever());
}

你的电话不关心他们在调用getAuthCallWhenNecessary时获得的AuthResponse是否真实,他们只关心他们从Auth获得响应对象

这是我(有点)记录的工作样本:https://gist.github.com/TormundsMember/ebcb3782b14477a3d5b72e898929fe61

答案 1 :(得分:1)

我认为您可以使用repeatWhen运算符和delay运算符的组合。

在令牌过期延迟后,重新订阅您的o​​bservable以获取新令牌。

希望这有帮助。

抱歉我的英文。

答案 2 :(得分:0)

我在我的案例中所做的可能有点矫枉过正,但它确实有效 - 我用我自己的代理类包装了所有的Retrofit接口:

  • 使用Proxy.newProxyInstance
  • 创建自己的Retrofit界面代理
  • 代理使用Retrofit.Builder()
  • 创建Retrofit实施
  • 在代理public Object invoke(Object proxy, Method method, Object[] args)中调用实际的Retrofit实现,在此调用之前您可以检查令牌是否有效,如果没有,则刷新令牌并在{{中调用Retrofit方法实现1}}
  • 如果由于401导致改装调用失败,您可以使用switchMap()检查此错误,刷新访问令牌并再次调用Retrofit方法实现。
  • (我还将结果存储在resultObservable.retryWhen(errorCheck)中,并且每当我的应用程序的一部分请求结果时(通过调用接口方法)都返回此主题,并且我只在单独的{时刷新网络中的结果已发出{1}}来电)