我有一个登录端点,通过它我收到authToken和refreshToken。第一个在一小时后到期,所以我应该使用第二个来刷新它并继续应用程序流程。
现在我的应用程序充满了遍布各处的改装调用,我可能会在任何特定时刻获得401
,所以每次刷新401
时我怎么能这样做发出令牌,然后重试原始请求?
这是我的刷新签名:
@POST("/auth/actions/refresh")
fun refreshToken(@Body tokenRefresh: TokenRefresh): Single<LoginResponse>
我考虑过使用方法withAuth()
创建一个基础知识库类,它接受任何Observable
/ Single
/ Flowable
然后应用此逻辑但我找不到方法实施它。
看到了很多实现,但没有一个符合我的需求......任何人都可以把我推向正确的方向吗?
This is the closest我发现,平面图上似乎有一些错误
答案 0 :(得分:0)
我刚遇到类似的要求,并提出了以下解决方案。这很简单,它仅尝试调用REST端点,如果该调用失败并显示HTTP 401,它将重新进行身份验证并再次重复该调用。否则,它只会发出原始错误。
fun <T> Single<T>.withAuth() = retryWhen { errors ->
var firstAttempt = true
errors.flatMapSingle { error ->
if (firstAttempt && error is HttpException && error.code() == 401) {
firstAttempt = false
reauthenticate()
} else {
Single.error(it)
}
}
}
其中重新认证功能具有以下签名:
fun reauthenticate(): Single<AnyAuthResponse>
请注意,具体的异常类型可能取决于您实际使用的HTTP实现,因此您可能希望更新条件以检测HTTP 401响应,但是代码应该为您提供解决问题的总体方法。 / p>
答案 1 :(得分:0)
我认为您可以在不修改所有通话的情况下执行此操作。将Authenticator
添加到改造中
Refreshing OAuth token using Retrofit without modifying all calls
答案 2 :(得分:0)
您可以使用Interceptor拦截每个请求,并检查它是否返回401
-未经授权的访问,并且iff然后刷新令牌并重播当前的API请求。
public final class SessionInterceptor implements Interceptor {
// gets intercept
@Override public Response intercept(@NonNull final Chain chain) throws IOException {
final Request request = chain.request();
final Response response = chain.proceed(request);
final ResponseBody responseBody = response.body();
if (response.code() == 401) {
synchronized (this) {
// Refresh your token
// Update your authToken + Refreshed token
final retrofit2.Response response = refreshToken();
}
}
// Replay the original request
// Perform request, here original request will be executed
final Request original = chain.request();
final Request.Builder builder = original.newBuilder();
// Set your new refreshed token
if (accessToken.isSet()) {
builder.header(AUTHORIZATION, String.format(BEARER,
accessToken.get()));
}
final Request request = builder.method(original.method(), original.body()).build();
return chain.proceed(request);
}
}