我创建了一个类来获取刷新令牌,如果该令牌在任何时候都过期了。 在进行其余的API调用之前,请始终先调用此类。
这是我的课程,
import android.content.Context;
import com.epic.ssb.data.TokenModel;
import com.epic.ssb.security.LogoutProcess;
import com.epic.ssb.security.TokenIdentifier;
import com.epic.ssb.util.Constant;
import java.io.IOException;
import java.net.HttpURLConnection;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;
import okhttp3.Interceptor;
import okhttp3.OkHttpClient;
import okhttp3.Request;
import okhttp3.Response;
import retrofit2.Call;
import retrofit2.Retrofit;
import retrofit2.converter.gson.GsonConverterFactory;
public class RefreshTokenInterceptor implements Interceptor {
private Lock lock = new ReentrantLock();
Context ctx;
public RefreshTokenInterceptor(Context context){
this.ctx = context;
}
@Override
public Response intercept(Chain chain) throws IOException {
chain.withConnectTimeout( 45, TimeUnit.SECONDS);
chain.withReadTimeout(45,TimeUnit.SECONDS);
chain.withWriteTimeout(45,TimeUnit.SECONDS);
Request request = chain.request();
Response response = chain.proceed(request);
if (response.code() == HttpURLConnection.HTTP_UNAUTHORIZED) {
if (lock.tryLock()) {
try {
OkHttpClient.Builder httpClient = new OkHttpClient.Builder();
httpClient.addInterceptor(new Interceptor() {
@Override
public Response intercept(Interceptor.Chain chain) throws IOException {
Request original = chain.request();
Request request = original.newBuilder()
.header("Content-Type", "application/json")
.header("X-Requested-With", "XMLHttpRequest")
.header("X-Authorization", "Bearer " + TokenIdentifier.getREFRESHTOKEN())
.method(original.method(), original.body())
.build();
return chain.proceed(request);
}
});
OkHttpClient client = httpClient.build();
Retrofit retrofit = new Retrofit.Builder()
.baseUrl(Constant.BASE_URL)
.addConverterFactory(GsonConverterFactory.create())
.client(client)
.build();
ApiService apiService = retrofit.create(ApiService.class);
Call<TokenModel> call = apiService.getTokenFromRefreshToken();
retrofit2.Response<TokenModel> response1 = call.execute();
if(response.body()!=null){
TokenModel tokenModel = response1.body();
TokenIdentifier.setTOKEN(tokenModel.getToken());
}
Request newRequest = recreateRequestWithNewAccessToken(chain);
return chain.proceed(newRequest);
} catch (Exception ex) {
LogoutProcess.logout(ctx);
return response;
} finally {
lock.unlock();
}
} else {
lock.lock();
lock.unlock();
Request newRequest = recreateRequestWithNewAccessToken(chain);
return chain.proceed(newRequest);
}
} else {
return response;
}
}
private Request recreateRequestWithNewAccessToken(Chain chain) {
String freshAccessToken = TokenIdentifier.getTOKEN();
return chain.request().newBuilder()
.header("Content-Type", "application/json")
.header("X-Requested-With", "XMLHttpRequest")
.header("X-Authorization", "Bearer " + freshAccessToken)
.method(chain.request().method(), chain.request().body())
.build();
}
}
注意:如果当前令牌已过期,则该类用于获取新令牌。
然后我随机访问了上面的类的以下异常,
W/System.err: java.net.SocketTimeoutException: timeout
W/System.err: at okio.Okio$4.newTimeoutException(Okio.java:232)
at okio.AsyncTimeout.exit(AsyncTimeout.java:285)
W/System.err: at okio.AsyncTimeout$1.write(AsyncTimeout.java:184)
at okio.RealBufferedSink.emitCompleteSegments(RealBufferedSink.java:179)
at okio.RealBufferedSink.write(RealBufferedSink.java:42)
at okhttp3.internal.http1.Http1Codec$FixedLengthSink.write(Http1Codec.java:295)
at okio.ForwardingSink.write(ForwardingSink.java:35)
at okhttp3.internal.http.CallServerInterceptor$CountingSink.write(CallServerInterceptor.java:149)
W/System.err: at okio.RealBufferedSink.emitCompleteSegments(RealBufferedSink.java:179)
at okio.RealBufferedSink.write(RealBufferedSink.java:48)
at okhttp3.RequestBody$1.writeTo(RequestBody.java:73)
at okhttp3.internal.http.CallServerInterceptor.intercept(CallServerInterceptor.java:72)
at okhttp3.internal.http.RealInterceptorChain.proceed(RealInterceptorChain.java:147)
at okhttp3.internal.connection.ConnectInterceptor.intercept(ConnectInterceptor.java:45)
W/System.err: at okhttp3.internal.http.RealInterceptorChain.proceed(RealInterceptorChain.java:147)
at okhttp3.internal.http.RealInterceptorChain.proceed(RealInterceptorChain.java:121)
at okhttp3.internal.cache.CacheInterceptor.intercept(CacheInterceptor.java:93)
at okhttp3.internal.http.RealInterceptorChain.proceed(RealInterceptorChain.java:147)
at okhttp3.internal.http.RealInterceptorChain.proceed(RealInterceptorChain.java:121)
W/System.err: at okhttp3.internal.http.BridgeInterceptor.intercept(BridgeInterceptor.java:93)
at okhttp3.internal.http.RealInterceptorChain.proceed(RealInterceptorChain.java:147)
at okhttp3.internal.http.RetryAndFollowUpInterceptor.intercept(RetryAndFollowUpInterceptor.java:126)
at okhttp3.internal.http.RealInterceptorChain.proceed(RealInterceptorChain.java:147)
at okhttp3.internal.http.RealInterceptorChain.proceed(RealInterceptorChain.java:121)
W/System.err: at com.epic.ssb.network.RefreshTokenInterceptor.intercept(RefreshTokenInterceptor.java:39)
at okhttp3.internal.http.RealInterceptorChain.proceed(RealInterceptorChain.java:147)
at okhttp3.internal.http.RealInterceptorChain.proceed(RealInterceptorChain.java:121)
at okhttp3.RealCall.getResponseWithInterceptorChain(RealCall.java:200)
at okhttp3.RealCall$AsyncCall.execute(RealCall.java:147)
at okhttp3.internal.NamedRunnable.run(NamedRunnable.java:32)
W/System.err: at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1167)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:641)
at java.lang.Thread.run(Thread.java:764)
W/System.err: Caused by: java.net.SocketException: Socket closed
at java.net.SocketOutputStream.socketWrite(SocketOutputStream.java:124)
at java.net.SocketOutputStream.write(SocketOutputStream.java:161)
at okio.Okio$1.write(Okio.java:79)
at okio.AsyncTimeout$1.write(AsyncTimeout.java:180)
W/System.err: ... 30 more
正如我在文章顶部提到的那样,这用于安全的Rest API调用。不适用于未经授权的Rest API调用。
为什么这是随机发生的?我应该添加更多步骤吗?