【问题标题】:Authentication and Authentication Header in OkHTTPOkHTTP 中的身份验证和身份验证标头
【发布时间】:2015-09-09 07:17:03
【问题描述】:

我正面临一个相当简单的情况,但我无法理解它。也许 OkHttp 大师可以照亮我的道路。

我在我的 Android 应用程序上使用PicassoRetrofitOkHttp 用于多种用途。耶!。正如我正确阅读的那样,开发人员应该努力保持 OkHttpClient (如阅读此处)。

考虑到这种方法,我希望我的任何 HTTP 调用(无论是 API 调用、图像加载、资源下载)到:

  1. 发送请求
  2. 如果收到 HTTP401,则发送另一个返回令牌的 HTTP 请求
  3. 收到该令牌后,将使用包含在标头中的该令牌重新发出调用
  4. 任何后续调用(无论是 API、资源还是图像调用)都应使用该令牌,直到收到下一个 HTTP401(无效令牌)。

当然,我会为 Retrofit 和 Picasso 重用 same 客户端。

我正在考虑的一种方法是混合使用Authenticator 和应用程序Interceptor。 Authenticator 应该捕获 HTTP401,但我可以让它同时发出另一个同步请求,存储令牌并激活新的拦截器吗?

【问题讨论】:

    标签: retrofit picasso okhttp


    【解决方案1】:

    看来我自己找到了解决该问题的方法,所以让我们将知识分享给大家。

    为此,OkHttp 已经提供了所有必要的钩子。

    1. 确保使用身份验证器
    2. 验证器成功后安装拦截器
    3. 使用正确的令牌返回请求。

    这也意味着Authenticator 处理 HTTP 以设置您的令牌(在另一个 android 服务中完成)。

    okHttpClient.setAuthenticator(new Authenticator() {
                @Override
                public Request authenticate(Proxy proxy, Response response) {
    
                    AccountManager accountManager = AccountManager.get(context);
                    Account[] accounts = accountManager.getAccountsByType(Authenticator.ACCOUNT_TYPE);
                    // No account, do not even try to authenticate
                    if (accounts.length == 0) {
                        Log.i(TAG, "... But we dont have any account yet, so I will just back off for now.");
                        return null;
                    }
    
                    Account account = accounts[0];
    
                    try {
                        final String mCurrentToken = accountManager.blockingGetAuthToken(account, "", false);
    
                        // For now, we just re-install blindly an interceptor
                        okHttpClient.interceptors().clear();
                        Log.i(TAG, "... Installing interceptor after authentication");
                        okHttpClient.interceptors().add(new Interceptor() {
                                @Override public Response intercept(Chain chain) throws IOException {
                                    Request request = chain.request();
                                    Request newReq = request.newBuilder()
                                        .addHeader("Authorization", mCurrentToken)
                                        .build();
                                    Response response = chain.proceed(newReq);
    
                                    return response;
                                }
                            });
                        Log.i(TAG, "Install temporary auth token in request");
                        return response.request().newBuilder()
                            .addHeader("Authorization", mCurrentToken)
                            .build();
    
                    } catch (OperationCanceledException e) {
                        Log.e(TAG, "Interrupted exception");
                        return null;
                    } catch (AuthenticatorException e) {
                        Log.e(TAG, "Authentication error");
                        return null;
                    } catch (IOException e) {
                        Log.e(TAG, "IO Error");
                        return null;                        
                    }
                }
    
    
                @Override
                public Request authenticateProxy(Proxy proxy, Response response) {
                    return null; // Null indicates no attempt to authenticate.
                }
            })
    

    有了这个,只需在 Picasso 和 Retrofit 中使用这个 OkClient。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2014-10-19
      • 2021-04-28
      • 1970-01-01
      • 2019-06-19
      • 2021-09-26
      • 2015-03-07
      • 2015-02-02
      • 2018-02-24
      相关资源
      最近更新 更多