我想在访问令牌过期时刷新它。我已经实现了 Authenticator,如下所示:
@Singleton
class TokenAuthenticator(
val authService: Lazy<AuthService>,
private val sharedPreferences: SharedPreferences
) : Authenticator {
override fun authenticate(route: Route?, response: Response): Request? {
return authRequestWithNewToken(response.request)
}
private fun authRequestWithNewToken(
request: Request
): Request? {
getFreshAccessToken()?.let { freshToken ->
return getNewRequest(request, freshToken)
}
return null
}
private fun getFreshAccessToken(): String? {
val refreshResponse = authService.get().refreshTokenTemp().execute()
if (refreshResponse.isSuccessful) {
val updatedAccessToken =
refreshResponse.body()?.data?.accessToken ?: return null
val updatedRefreshToken =
refreshResponse.body()?.data?.refreshToken ?: return null
updateToken(updatedAccessToken, updatedRefreshToken)
Timber.tag("TOKEN")
.d("Auth Updated token\n AccessToken: $updatedAccessToken \n RefreshToken: $updatedRefreshToken")
return updatedAccessToken
} else {
return null
}
}
private fun getNewRequest(request: Request, accessToken: String): Request {
return request.newBuilder()
.header(
AppConstants.PARAMS.AUTH,
AppConstants.PARAMS.BEARER + accessToken
)
.header("Accept", "application/json")
.header("User-Agent", AppConstants.PARAMS.USER_AGENT)
.build()
}
private fun updateToken(accessToken: String, refreshToken: String) {
with(sharedPreferences.edit()) {
putString(AppConstants.SHAREDPREFERENCE.ACCESS_TOKEN, accessToken)
putString(AppConstants.SHAREDPREFERENCE.REFRESH_TOKEN, refreshToken).apply()
}
AppVariables.SessionData.accessToken = accessToken
AppVariables.SessionData.refreshToken = refreshToken
Timber.tag("TOKEN").d("Token Refreshed")
}
}
即使使用此功能后,由于发生并行 API 调用,我的应用程序仍然超时,并且用户被带到登录屏幕。
即使花了很多时间我也无法弄清楚出了什么问题。
我看到人们在尝试
@synchronised
,我尝试实施但没有成功。
最后我看到了this,他添加了这样的调度程序:
@Singleton
@Provides
fun provideOkhttpClient(tokenAuthenticator: TokenAuthenticator): OkHttpClient {
//***********like this**********************//
val dispatcher = Dispatcher()
dispatcher.maxRequests = 1
//******************************************//
return OkHttpClient.Builder()
.dispatcher(dispatcher)
.connectTimeout(180, TimeUnit.SECONDS)
.readTimeout(180, TimeUnit.SECONDS)
.writeTimeout(180, TimeUnit.SECONDS)
.authenticator(tokenAuthenticator)
.addInterceptor(TokenInterceptor())
.build()
}
这似乎解决了我的问题。但是,我不知道这意味着什么。是否建议在生产中使用?
我可以在文档中看到以下内容:
同时执行的最大请求数。上面这个 请求在内存中排队,等待正在运行的调用完成。 如果在调用此函数时有超过 maxRequests 的请求正在运行, 这些请求将继续进行。
我是否错过了一些可能会在以后咬我屁股的东西?
您可以尝试此刷新令牌。
public class TokenManager {
private String accessToken;
private String refreshToken;
private long tokenExpirationTime;
// Other methods for setting, getting, and checking token details
}
public class TokenRefreshInterceptor implements Interceptor {
@Override
public Response intercept(Chain chain) throws IOException {
Request originalRequest = chain.request();
String accessToken = TokenManager.getInstance().getAccessToken();
if (accessToken != null && !accessToken.isEmpty()) {
// Add the access token to the request headers
Request modifiedRequest = originalRequest.newBuilder()
.header("Authorization", "Bearer " + accessToken)
.build();
return chain.proceed(modifiedRequest);
}
return chain.proceed(originalRequest);
}
}
public class ApiService {
// Retrofit API interfaces
}
public class ApiClient {
private static Retrofit retrofit;
public static Retrofit getClient() {
if (retrofit == null) {
OkHttpClient client = new OkHttpClient.Builder()
.addInterceptor(new TokenRefreshInterceptor())
.build();
retrofit = new Retrofit.Builder()
.baseUrl(BASE_URL)
.client(client)
.addConverterFactory(GsonConverterFactory.create())
.build();
}
return retrofit;
}
}
public class ApiCaller {
public void makeApiCall() {
ApiService apiService = ApiClient.getClient().create(ApiService.class);
Call<ApiResponse> call = apiService.getSomeData();
call.enqueue(new Callback<ApiResponse>() {
@Override
public void onResponse(Call<ApiResponse> call, Response<ApiResponse> response) {
// Handle API response
}
@Override
public void onFailure(Call<ApiResponse> call, Throwable t) {
// Handle API failure
}
});
}
}