我通过编写Interceptor
for解决了这个问题OkHttp
。它检查网络调用的状态码。如果是 403,则调用 Auth0 服务器并请求新的 id_token。然后在原始请求的新版本中使用此令牌。
为了进行测试,我编写了一个小型网络服务器来检查TestHeader是否失败,如果失败则返回403。
public class AuthenticationInterceptor implements Interceptor {
@Override
public Response intercept(Chain chain) throws IOException {
Request originalRequest = chain.request();
Request authenticationRequest = originalRequest.newBuilder()
.header("TestHeader", "fail")
.build();
Response origResponse = chain.proceed(authenticationRequest);
// server should give us a 403, since the header contains 'fail'
if (origResponse.code() == 403) {
String refreshToken = "abcd"; // you got this from Auth0 when logging in
// start a new synchronous network call to Auth0
String newIdToken = fetchNewIdTokenFromAuth0(refreshToken);
// make a new request with the new id token
Request newAuthenticationRequest = originalRequest.newBuilder()
.header("TestHeader", "succeed")
.build();
// try again
Response newResponse = chain.proceed(newAuthenticationRequest);
// hopefully we now have a status of 200
return newResponse;
} else {
return origResponse;
}
}
}
然后我将此拦截器附加到我插入改造适配器的 OkHttpClient:
// add the interceptor to an OkHttpClient
public static OkHttpClient getAuthenticatingHttpClient() {
if (sAuthenticatingHttpClient == null) {
sAuthenticatingHttpClient = new OkHttpClient();
sAuthenticatingHttpClient.interceptors().add(new AuthenticationInterceptor());
}
return sAuthenticatingHttpClient;
}
// use the OkHttpClient in a Retrofit adapter
mTestRestAdapter = new RestAdapter.Builder()
.setClient(new OkClient(Network.getAuthenticatingHttpClient()))
.setEndpoint("http://ip_of_server:port")
.setLogLevel(RestAdapter.LogLevel.FULL)
.build();
// call the Retrofit method on buttonclick
ViewObservable.clicks(testNetworkButton)
.map(new Func1<OnClickEvent, Object>() {
@Override
public Object call(OnClickEvent onClickEvent) {
return mTestRestAdapter.fetchTestResponse();
}
}
)