如何刷新改进2/rxJava中的ACCESS-TOKEN

我发出请求(任何授权,注册等),然后我发现我需要更新ACCESS-TOKEN,即得到错误401。如何刷新改进2/rxJava中的ACCESS-TOKEN

这里是授权请求:

BaseApplication.getApiClient() 

.signIn(accessToken, body)

.subscribeOn(Schedulers.io())

.observeOn(AndroidSchedulers.mainThread())

.subscribe(new SingleObserver<UserProfile>() {

@Override

public void onSubscribe(Disposable d) {

Log.d("-- SignInOnSubscribe", "Subscribed!");

}

@Override

public void onSuccess(UserProfile userProfile) {

if (userProfile.getErrorDetails() != null) {

onSignInFinishedCallback.onLoginFailure(userProfile.getErrorDetails());

Log.d("-- SignInOnError", userProfile.getErrorDetails());

} else {

onSignInFinishedCallback.onLoginSuccess(userProfile);

profileRepository.updateUserProfile(userProfile);

Log.d("-- SignInOnSuccess", userProfile.getName());

}

}

@Override

public void onError(Throwable e) {

Log.d("-- SignInOnError", e.getMessage());

if (e.getMessage().equals(Constants.CODE_UNAUTHORIZED)){

// Action on error 401

}

onSignInFinishedCallback.onLoginFailure(e.getMessage());

}

});

的API请求:

@POST("/api/login") 

Single<UserProfile> getAccessToken(@Body Map<String, String> requestBody);

@POST("/api/abonent/login")

Single<UserProfile> signIn(@Header("X-ACCESS-TOKEN") String accessToken,

@Body Map<String, String> requestBody);

例如,该授权要求是request 1,接收TOKENquery 2该请求。

问题:我如何更新TOKEN如果我query 1得到一个错误和query 2成功后,回做query 1

回答:

我不确定您是如何收到新令牌的,因为返回类型为getAccessToken()的是Single<UserProfile>。我想这应该是Single<String>代替。也许这是不是这种情况,您会收到令牌在页眉或作为UserProfile领域。在这两种情况下,你可以从下面的解决方案的想法,把它调整到你的情况。

的方法是,我们从原来的一个一个使用令牌存储装置,它拥有最先进的最新令牌创建一个新的观测。我们处理使用composeonErrorResumeNext使令牌刷新请求时,新令牌保存到令牌存储装置,和原来的请求被重新尝试新的令牌这一次的401错误。

如需更详细的说明,请参见下面的代码中的注释:

public void signIn(final Map<String, String> body) { 

Single

// Wrap the original request with a "defer" so that the access token is

// evaluated each time it is called. This is important because the refreshed

// access token should be used the second time around.

.defer(new Callable<SingleSource<UserProfile>>() {

@Override

public SingleSource<UserProfile> call() throws Exception {

return BaseApplication.getApiClient()

.signIn(accessTokenStore.getAccessToken(), body);

}

})

// Compose it with a transformer that refreshes the token in the token store and

// retries the original request, this time with the refreshed token.

.compose(retryOnNotAuthorized(body))

// The code remains the same from here.

.subscribeOn(Schedulers.io())

.observeOn(AndroidSchedulers.mainThread())

.subscribe(new SingleObserver<UserProfile>() {

@Override

public void onSubscribe(Disposable d) {

Log.d("-- SignInOnSubscribe", "Subscribed!");

}

@Override

public void onSuccess(UserProfile userProfile) {

if (userProfile.getErrorDetails() != null) {

onSignInFinishedCallback.onLoginFailure(userProfile.getErrorDetails());

Log.d("-- SignInOnError", userProfile.getErrorDetails());

} else {

onSignInFinishedCallback.onLoginSuccess(userProfile);

profileRepository.updateUserProfile(userProfile);

Log.d("-- SignInOnSuccess", userProfile.getName());

}

}

@Override

public void onError(Throwable e) {

Log.d("-- SignInOnError", e.getMessage());

if (e.getMessage().equals(Constants.CODE_UNAUTHORIZED)) {

// Action on error 401

}

onSignInFinishedCallback.onLoginFailure(e.getMessage());

}

});

}

@NonNull

private SingleTransformer<UserProfile, UserProfile> retryOnNotAuthorized(final Map<String, String> body) {

return new SingleTransformer<UserProfile, UserProfile>() {

@Override

public SingleSource<UserProfile> apply(final Single<UserProfile> upstream) {

// We use onErrorResumeNext to continue our Single stream with the token refresh

// and the retrial of the request.

return upstream.onErrorResumeNext(new Function<Throwable, SingleSource<? extends UserProfile>>() {

@Override

public SingleSource<UserProfile> apply(Throwable throwable) throws Exception {

if (throwable instanceof HttpException

&& ((HttpException) throwable).code() == 401) {

return BaseApplication.getApiClient().getAccessToken(body)

// I always use doOnSuccess() for non-Rx side effects, such as caching the token.

// I think it's clearer than doing the caching in a map() or flatMap().

.doOnSuccess(new Consumer<String>() {

@Override

public void accept(String accessToken) throws Exception {

// Save the access token to the store for later use.

accessTokenStore.storeAccessToken(accessToken);

}

})

// We don't need the result of getAccessToken() any more, so I

// think it's cleaner to convert the stream to a Completable.

.toCompletable()

// After the token is refreshed and stored, the original request

// should be repeated.

.andThen(upstream);

}

// If the error was not 401, pass through the original error

return Single.error(throwable);

}

});

}

};

}

更新:令牌存储装置仅仅是一个带有get和储存方法的常规接口。你应该实现它无论是作为一个POJO(存储在字段中的令牌),或者你可以在令牌存储在共享的偏好,使得令牌生存的应用程序重新启动。

以上是 如何刷新改进2/rxJava中的ACCESS-TOKEN 的全部内容, 来源链接: utcz.com/qa/266479.html

回到顶部