android - 如何在不到处添加特定代码的情况下处理 auth0 403 错误 (Retrofit/okhttp/RxAndroid)

标签 android retrofit rx-java okhttp auth0

我正在使用 Auth0,它为我提供了一个 JWT(json 网络 token )和一个刷新 token 。我在 http header 中使用此 JWT 与我的后端进行通信。

当服务器确定 JWT 已过期时,它可能会给我一个 403。在这种情况下,我可以要求 Auth0 使用 refreshtoken 给我颁发一个新的 JWT。这意味着我调用 Auth0 后端,将 refreshtoken 传递给它,它会给我一个新的 JWT,然后我可以在我的请求中使用它。

我的问题是,如何在我所有的网络代码中高效地编写此行为?我将与几个端点通信,它们都可能返回 403。

我想我应该先制作一个拦截器,将 JWT 添加到所有请求。

然后应该有检测到 403 的行为,悄悄地对 Auth0 进行网络调用,检索新的 JWT。然后应再次尝试原始请求,并在其 header 中使用新的 JWT。

所以我宁愿让这个 403 处理在我的其他代码不可见的地方,而且绝对不必在所有地方都重写它。

任何关于如何实现这一目标的指示将不胜感激。

--

需要说明的是,我基本上是在寻找有关如何使用 RxAndroid Observables 实现这一点的指示。当某个 Observable 发现 403 时,它应该“注入(inject)”一个新的网络调用。

最佳答案

我通过为 OkHttp 编写一个 Interceptor 解决了这个问题。它检查网络调用的状态代码。如果是 403,调用 Auth0 服务器并请求一个新的 id_token。然后在原始请求的新版本中使用此 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;
        }
    }
}

然后我将这个拦截器附加到我插入 Retrofit 适配器的 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();
             }
         }
    )

关于android - 如何在不到处添加特定代码的情况下处理 auth0 403 错误 (Retrofit/okhttp/RxAndroid),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/30461420/

相关文章:

java - Try/Catch/Finally 语句中的空指针异常

android - 如何让 exoplayer 播放 Drive 中的视频

android - 无法在 Android Retrofit2 converter-simplexml 库中为我的类创建转换器

php - 使用 Android 将字符串数组传递到 PHP 文件

junit - 将 MockWebServer 与 Robolectric 结合使用

java - 单个 Observable 是否会按顺序通知其所有观察者?

rx-java - 使用 RxJava2 下载带有进程的文件

java - RxJava 允许多次 onError 调用

android - 使用 asmack 向 gtalk 发送多条聊天消息;乱序

android - 如何在 Flutter 应用程序中显示原生 Android View ?