【发布时间】:2014-12-24 04:31:06
【问题描述】:
我正在尝试使用 Retrofit 实现摘要式身份验证。我的第一个解决方案在 OkHttpClient 上设置了 OkHttp 的 Authenticator 的实现:
class MyAuthenticator implements Authenticator {
private final DigestScheme digestScheme = new DigestScheme();
private final Credentials credentials = new UsernamePasswordCredentials("user", "pass");
@Override public Request authenticate(Proxy proxy, Response response) throws IOException {
try {
digestScheme.processChallenge(new BasicHeader("WWW-Authenticate", response.header("WWW-Authenticate")));
HttpRequest request = new BasicHttpRequest(response.request().method(), response.request().uri().toString());
String authHeader = digestScheme.authenticate(credentials, request).getValue();
return response.request().newBuilder()
.addHeader("Authorization", authHeader)
.build();
} catch (Exception e) {
throw new AssertionError(e);
}
}
@Override public Request authenticateProxy(Proxy proxy, Response response) throws IOException {
return null;
}
}
这对于通过 Retrofit 的 GET 请求非常有效。但是,如this StackOverflow question 中所述,POST 请求会导致“无法重试流式 HTTP 正文”异常:
Caused by: java.net.HttpRetryException: Cannot retry streamed HTTP body
at com.squareup.okhttp.internal.http.HttpURLConnectionImpl.getResponse(HttpURLConnectionImpl.java:324)
at com.squareup.okhttp.internal.http.HttpURLConnectionImpl.getResponseCode(HttpURLConnectionImpl.java:508)
at com.squareup.okhttp.internal.http.HttpsURLConnectionImpl.getResponseCode(HttpsURLConnectionImpl.java:136)
at retrofit.client.UrlConnectionClient.readResponse(UrlConnectionClient.java:94)
at retrofit.client.UrlConnectionClient.execute(UrlConnectionClient.java:49)
at retrofit.RestAdapter$RestHandler.invokeRequest(RestAdapter.java:357)
at retrofit.RestAdapter$RestHandler.invoke(RestAdapter.java:282)
at $Proxy3.login(Native Method)
at com.audax.paths.job.LoginJob.onRunInBackground(LoginJob.java:41)
at com.audax.library.job.AXJob.onRun(AXJob.java:25)
at com.path.android.jobqueue.BaseJob.safeRun(BaseJob.java:108)
at com.path.android.jobqueue.JobHolder.safeRun(JobHolder.java:60)
at com.path.android.jobqueue.executor.JobConsumerExecutor$JobConsumer.run(JobConsumerExecutor.java:172)
at java.lang.Thread.run(Thread.java:841)
Jesse Wilson 解释说,我们无法在验证后重新发送我们的请求,因为 POST 正文已被丢弃。但是由于摘要认证,我们需要返回的WWW-Authenticate 标头,因此我们不能使用RequestInterceptor 来简单地添加标头。也许可以在 RequestInterceptor 中执行单独的 HTTP 请求,并在响应中使用 WWW-Authenticate 标头,但这似乎很麻烦。
有没有办法解决这个问题?
【问题讨论】:
标签: android authentication retrofit okhttp