使用Basic Auth时,HTTPClient会发出两个请求吗?

时间:2012-03-02 19:23:49

标签: java basic-authentication apache-httpclient-4.x

我一直在使用HTTPClient版本4.1.2来尝试访问需要基本身份验证的REST over HTTP API。这是客户端代码:

DefaultHttpClient httpClient = new DefaultHttpClient(new ThreadSafeClientConnManager());
// Enable HTTP Basic Auth
httpClient.getCredentialsProvider().setCredentials(
    new AuthScope(AuthScope.ANY_HOST, AuthScope.ANY_PORT), 
    new UsernamePasswordCredentials(this.username, this.password));

HttpHost proxy = new HttpHost(this.proxyURI.getHost(), this.proxyURI.getPort());

httpClient.getParams().setParameter(ConnRouteParams.DEFAULT_PROXY, proxy);

当我构建POST请求时,如下所示:

HttpPost request = new HttpPost("http://my/url");
request.addHeader(new BasicHeader("Content-type", "application/atom+xml; type=entry")); // required by vendor
request.setEntity(new StringEntity("My content"));

HttpResponse response = client.execute(request);

我在Charles Proxy中看到有两个请求被发送。一个没有Authorization: Basic ...标题,一个它。第一个失败的是401,正如你所料,但是第二个失败的是201。

有谁知道为什么会这样?谢谢!

修改

我应该明确表示我已经查看了this question,但正如您所看到的那样,我以同样的方式设置AuthScope并且它没有解决我的问题。此外,我每次发出请求时都会创建一个新的HttpClient(虽然我使用相同的ConnectionManager),但即使我对多个请求使用相同的HttpClient,问题仍然存在仍然存在。

编辑2:

所以看起来@LastCoder的建议就是这样做的。请参阅this answer另一个问题。问题源于我对HTTP规范缺乏了解。我要做的是称为“抢占式身份验证”和HttpClient docs mention it here。值得庆幸的是,与上述相关的答案是一种更短更简洁的方法。

2 个答案:

答案 0 :(得分:11)

不是使用.setCredentials()而是为什么不编码USERNAME:PASSWORD并使用.addHeader()

添加身份验证标头

答案 1 :(得分:2)

这意味着您的服务器/目标端点正在为每个客户端请求创建一个新会话。这会强制您的每一个请求都经过一次握手,这意味着客户首先拨打电话并意识到需要授权,然后是授权。您需要做的是先发下授权,如下所示:

httpClient.getParams()setAuthenticationPreemptive(真);

只是了解您可以记录客户端请求标头的过程,以便了解客户端发送和接收的内容: 看看是否有效。