在 Okhttp 中处理身份验证

Posted

技术标签:

【中文标题】在 Okhttp 中处理身份验证【英文标题】:Handling Authentication in Okhttp 【发布时间】:2015-06-09 23:32:11 【问题描述】:

我将OkHttp 2.3 与基本身份验证请求一起使用,根据 OKHttp 文档,它会自动重试未经身份验证的请求,但是每当我提供无效凭据时,请求都会花费太多时间,最后我得到了这个异常:

java.net.ProtocolException: 后续请求太多:21

如何防止 OkHttp 自动重试未经身份验证的请求,而是返回 401 Unauthorized

【问题讨论】:

【参考方案1】:
protected Authenticator getBasicAuth(final String username, final String password) 
    return new Authenticator() 
        private int mCounter = 0;

        @Override
        public Request authenticate(Proxy proxy, Response response) throws IOException 
            if (mCounter++ > 0) 
                throw new AuthenticationException(
                        AuthenticationException.Type.INVALID_LOGIN, response.message());
            

            String credential = Credentials.basic(username, password);
            return response.request().newBuilder().header("Authorization", credential).build();
        

        @Override
        public Request authenticateProxy(Proxy proxy, Response response) throws IOException 
            return null;
        
    ;

在我的 Authenticator 中,我只计算尝试次数 - 在 X 次尝试后,我抛出异常。

【讨论】:

【参考方案2】:

有效的 Traxdata 答案的修改版本:

protected Authenticator getBasicAuth(final String username, final String password) 
    return new Authenticator() 
        private int mCounter = 0;

        @Override
        public Request authenticate(Route route, Response response) throws IOException 
            Log.d("OkHttp", "authenticate(Route route, Response response) | mCounter = " + mCounter);
            if (mCounter++ > 0) 
                Log.d("OkHttp", "authenticate(Route route, Response response) | I'll return null");
                return null;
             else 
                Log.d("OkHttp", "authenticate(Route route, Response response) | This is first time, I'll try to authenticate");
                String credential = Credentials.basic(username, password);
                return response.request().newBuilder().header("Authorization", credential).build();
            
        
    ;

那么你需要:

OkHttpClient.Builder builder = new OkHttpClient.Builder();
builder.authenticator(getBasicAuth("username", "pass"));
retrofit = new Retrofit.Builder()
            .baseUrl(BASE_URL)
            .client(builder.build())
            .addConverterFactory(GsonConverterFactory.create())
            .build();

就是这样。

【讨论】:

以上是关于在 Okhttp 中处理身份验证的主要内容,如果未能解决你的问题,请参考以下文章

具有基本身份验证的 Android OkHttp

带有身份验证的 okhttp 发布请求

OkHttp + Retrofit libssl 以两种方式崩溃 SSL 身份验证

okHttp 3.x身份验证器未被调用

OkHttp 响应缓存返回垃圾文本

在 Apollo 中处理未经身份验证的响应