【发布时间】:2022-01-22 15:50:29
【问题描述】:
我正在使用Authenticator(okhttp3) 类的authenticate 方法来提供api 的refreshtoken。
在该方法中,我使用 httpClient.addInterceptor 调用 refreshtoken api 来提供新令牌
但使用授权令牌发出 create
它向其他 api 提供更新的授权令牌,但仅在 refreshtoken apicall 中,它在后端获取他们以前的授权令牌,尽管在 android 端提供更新的 refreshtoken 作为标头
示例:
当运行应用程序时,时间标记是“ABC” 过期后,新的刷新令牌是“xyw” 在 "xyw" 过期后 - 然后将 "xyw" 作为 oldAccessToken - 更新的 refreshtoken 是 "pqr"
现在当“pqr”过期时,它会使用“xyw”而不是“pqr”
它仅在 refreshtoken apicall 中产生此问题。
我无法找到此问题的主要原因
谁能告诉我为什么会提出这个问题?
代码:
使用 post 方法调用主 api :
public static void post(String url, String json, Context context, Callback callback) {
okHttpClient = new OkHttpClient().newBuilder()
.connectTimeout(10, TimeUnit.SECONDS)
.callTimeout(60,TimeUnit.SECONDS)
.writeTimeout(60, TimeUnit.SECONDS)
.readTimeout(60, TimeUnit.SECONDS)
.authenticator(new TokenAuthenticator(context))
.addInterceptor(new AccessTokenInterceptor(context)).build();
RequestBody body = RequestBody.create(json,mediaType);
System.out.println("J:> 1 main Token ::"+getToken(context));
Request request = new Request.Builder()
.url(url)
.header(AUTHORIZATION,getToken(context))
.post(body)
.build();
Call call = okHttpClient.newCall(request);
call.enqueue(callback);
}
AccessTokenInterceptor:
public class AccessTokenInterceptor implements Interceptor {
private Context mContext;
public AccessTokenInterceptor(Context mContext) {
this.mContext = mContext;
}
@NonNull
@Override
public Response intercept(@NonNull Chain chain) throws IOException {
System.out.println("J:> AUTH intercept inside...");
Request request = chain.request()
.newBuilder()
.addHeader(AUTHORIZATION, APIServices.getToken(mContext))
.build();
return chain.proceed(request);
}
}
令牌验证器:
public Request authenticate(@Nullable Route route, @NonNull Response response) throws IOException {
if (!response.request().header(AUTHORIZATION).equals(APIServices.getToken(mContext)))
return null;
String accessToken = null;
ApiInterface apiService = getAdapterRefresh(response.request().header(AUTHORIZATION)).create(ApiInterface.class);
Call<JwtRefreshTokenResponseModel> call = apiService.requestAccessToken();
try {
retrofit2.Response responseCall = call.execute();
JwtRefreshTokenResponseModel responseRequest = (JwtRefreshTokenResponseModel) responseCall.body();
if (responseRequest != null) {
String data = responseRequest.getToken();
accessToken = data;
//store token in session
}
}catch (Exception ex){
Log.d("ERROR", "onResponse: "+ ex.toString());
ex.printStackTrace();
}
if (accessToken != null) {
// retry the failed 401 request with new access token
return response.request().newBuilder()
.header("Authorization", accessToken) // use the new access token
.build();
}else{
return null;
}
}
getAdapterRefresh:
public Retrofit getAdapterRefresh(String token) {
if (retrofitRefresh==null) {
final OkHttpClient.Builder httpClient = new OkHttpClient.Builder().
connectTimeout(10, TimeUnit.SECONDS)
.callTimeout(60,TimeUnit.SECONDS)
.writeTimeout(60, TimeUnit.SECONDS)
.readTimeout(60, TimeUnit.SECONDS);
httpClient.addInterceptor(new Interceptor() {
@Override
public Response intercept(Chain chain) throws IOException {
Request request = chain.request()
.newBuilder()
// add Authorization key on request header
// key will be using refresh token
.addHeader(AUTHORIZATION,token)
.build();
return chain.proceed(request);
}
});
Gson gson = new GsonBuilder()
.setLenient()
.create();
retrofitRefresh= new Retrofit.Builder()
.baseUrl(BASE_URL)
.addConverterFactory(GsonConverterFactory.create(gson))
.client(httpClient.build())
.build();
}
return retrofitRefresh;
}
提前致谢
【问题讨论】:
-
我不会在令牌刷新时重建 Retrofit 或 OkHttpClient 实例。您已经有一个拦截器,您只能使用 AccessTokenInterceptor,并检查响应、请求新令牌并更新自身和保存的令牌。然后它都在一个地方,而不是在 Authenticator + Interceptor + DI 之间分开。
-
@YuriSchimke 你能举例说明你在说什么吗?
-
stackoverflow上有很多类似的问题,比如stackoverflow.com/questions/31021725/…和stackoverflow.com/questions/55688352/…
-
@YuriSchimke 好的...感谢您的帮助。我会试试的
标签: java android okhttp interceptor refresh-token