【问题标题】:Android - Configuring Retrofit/Apache HttpClient for Digest AuthAndroid - 为 Digest Auth 配置 Retrofit/Apache HttpClient
【发布时间】:2015-09-09 10:39:00
【问题描述】:

我正在开发一个 Android 项目并尝试让 Digest Authentication 与 Retrofit 一起使用。我有点惊讶 Retrofit 本身并不支持它(或者更准确地说,OkHttp 不支持它),但我想没有必要抱怨。

我在这里浏览了很多线程,看来正确的解决方案是将 Apache HttpClient(本机支持 Digest Auth)与 Retrofit 集成。这需要使用 retrofit.client.Client 实现包装 HttpClient。 Retrofit 传入的值必须被解析并构建到一个新的 HttpClient 响应中,然后将其发送回 Retrofit 以正常处理。感谢 Jason Tu 和他的例子:https://gist.github.com/nucleartide/24628083decb65a4562c

问题是,它不起作用。我每次都收到 401 Unauthorized,我不清楚为什么。这是我的客户端 impl:

public class AuthClientRedirector implements Client {
    private final CloseableHttpClient delegate;

    public AuthClientRedirector(String user, String pass, String hostname, String scope) {
        Credentials credentials = new UsernamePasswordCredentials(user, pass);
        AuthScope authScope = new AuthScope(hostname, 443, scope);

        CredentialsProvider credentialsProvider = new BasicCredentialsProvider();
        credentialsProvider.setCredentials(authScope, credentials);

        delegate = HttpClientBuilder.create()
        .setDefaultCredentialsProvider(credentialsProvider)
        .build();
   }

    @Override 
    public Response execute(Request request) {
    //
    // We're getting a Retrofit request, but we need to execute an Apache
    // HttpUriRequest instead. Use the info in the Retrofit request to create
    // an Apache HttpUriRequest.
    //
    String method = request.getMethod();

    ByteArrayOutputStream bos = new ByteArrayOutputStream();
    if (request.getBody() != null) {
        try {
            request.getBody().writeTo(bos);
        } catch (IOException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
    }
    String body = new String(bos.toByteArray());

    HttpUriRequest wrappedRequest;
    switch (method) {
    case "GET":
        wrappedRequest = new HttpGet(request.getUrl());
        break;
    case "POST":
        wrappedRequest = new HttpPost(request.getUrl());
        wrappedRequest.addHeader("Content-Type", "application/xml");
        try {
            ((HttpPost) wrappedRequest).setEntity(new StringEntity(body));
        } catch (UnsupportedEncodingException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
        break;
    case "PUT":
        wrappedRequest = new HttpPut(request.getUrl());
        wrappedRequest.addHeader("Content-Type", "application/xml");
        try {
            ((HttpPut) wrappedRequest).setEntity(new StringEntity(body));
        } catch (UnsupportedEncodingException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
        break;
    case "DELETE":
        wrappedRequest = new HttpDelete(request.getUrl());
        break;
    default:
        throw new AssertionError("HTTP operation not supported.");
    }

CloseableHttpResponse apacheResponse = null;
try {
    apacheResponse = delegate.execute(wrappedRequest);
} catch (IOException e) {
    // TODO Auto-generated catch block
    e.printStackTrace();
}

if(apacheResponse!=null){
    // Perform the HTTP request.
    CloseableHttpResponse response = null;
    try {
        response = delegate.execute(wrappedRequest);

        // Return a Retrofit response.
        List<Header> retrofitHeaders = toRetrofitHeaders(
                response.getAllHeaders());
        TypedByteArray responseBody;
        if (response.getEntity() != null) {
            responseBody = new TypedByteArray("",
                    toByteArray(response.getEntity()));
        } else {
            responseBody = new TypedByteArray("",
                    new byte[0]);
        }
        System.out.println("this is the response");
        System.out.println(new String(responseBody.getBytes()));
        return new retrofit.client.Response(request.getUrl(),
                response.getStatusLine().getStatusCode(),
                response.getStatusLine().getReasonPhrase(), retrofitHeaders,
                responseBody);
    } catch (ClientProtocolException e) {
        // TODO Auto-generated catch block
        e.printStackTrace();
    } catch (IOException e) {
        // TODO Auto-generated catch block
        e.printStackTrace();
    } finally {
        if (response != null) {
            try {
                response.close();                       
            } catch (IOException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }
        }
    }   
}
    //failed to return a new retrofit Client
    return null;
}

private List<Header> toRetrofitHeaders(org.apache.http.Header[] headers) {
    List<Header> retrofitHeaders = new ArrayList<>();
    for (org.apache.http.Header header : headers) {
        retrofitHeaders.add(new Header(header.getName(), header.getValue()));
    }
    return retrofitHeaders;
}

private byte[] toByteArray(HttpEntity entity) throws IOException {
    ByteArrayOutputStream bos = new ByteArrayOutputStream();
    entity.writeTo(bos);
    return bos.toByteArray();
}

}

我的改造配置如下:

public final RestAdapter configureService(){

AuthClientRedirector digestAuthMgr = new AuthClientRedirector(username,password,"myhostname","public");

RestAdapter.Builder builder = new RestAdapter.Builder()
.setEndpoint("http://myhostname:8003/endpoint")
.setLogLevel(RestAdapter.LogLevel.FULL)
.setClient(digestAuthMgr);
return builder.build();
}

我很困惑为什么我总是从服务器返回 401。我已经完成了响应构建过程,它对我来说看起来很干净,所以我想我错过了一些基本的东西。凭据很好,我已经在应用程序之外验证了它们。以前有人走过这条路吗?

【问题讨论】:

    标签: android authentication apache-httpclient-4.x retrofit digest-authentication


    【解决方案1】:

    您正在使用端口号 443 进行身份验证。

    AuthScope authScope = new AuthScope(hostname, 443, scope);
    

    但是,您的真实端口号似乎是8003

    RestAdapter.Builder builder = new RestAdapter.Builder()
    .setEndpoint("http://myhostname:8003/endpoint")
    

    那么,像下面这样使用端口号8003进行身份验证怎么样?

    AuthScope authScope = new AuthScope(hostname, 8003, scope);
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2012-04-07
      • 2019-03-05
      • 1970-01-01
      相关资源
      最近更新 更多