【发布时间】:2013-02-26 23:18:53
【问题描述】:
我一直在使用 HTTPClient 版本 4.1.2 来尝试通过需要基本身份验证的 HTTP API 访问 REST。这是客户端代码:
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 规范缺乏了解。我要做的就是所谓的“抢先式身份验证”和HttpClientdocs mention it here。值得庆幸的是,上面链接的答案是一种更短更简洁的方法。
【问题讨论】:
-
我注意到使用soap-ui时发生了同样的事情,即使指定了凭据。
-
我想知道这是否真的是正常行为。客户端发出一个不假设任何身份验证的 http 请求,然后被告知(通过 401)需要基本身份验证。理论上基本身份验证可以先发制人完成,但其他身份验证方案(例如摘要)需要额外协商
-
@seand 你知道我确实考虑过这一点,但我不知道这是否内置在 HTTP 协议中或类似的东西中。
-
@devslab http 客户端可以预先发送基本的身份验证标头(@LastCoder 提到了如何做到这一点)。我在想 HttClient 不知道服务器需要基本身份验证。你事先告诉它信用,但没有告诉它协议。如果有办法告诉它“这是基本的”身份验证,它可能会减少额外的跳跃。
-
原来@LastCoder 发现这样做是 HTTP 规范的一部分。
标签: java basic-authentication apache-httpclient-4.x