我一直在使用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。值得庆幸的是,与上述相关的答案是一种更短更简洁的方法。
答案 0 :(得分:11)
不是使用.setCredentials()而是为什么不编码USERNAME:PASSWORD并使用.addHeader()
添加身份验证标头答案 1 :(得分:2)
这意味着您的服务器/目标端点正在为每个客户端请求创建一个新会话。这会强制您的每一个请求都经过一次握手,这意味着客户首先拨打电话并意识到需要授权,然后是授权。您需要做的是先发下授权,如下所示:
httpClient.getParams()setAuthenticationPreemptive(真);
只是了解您可以记录客户端请求标头的过程,以便了解客户端发送和接收的内容: 看看是否有效。