从HttpClient 4.3开始,我一直在使用HttpClientBuilder。我正在连接到具有基本身份验证的REST服务。我将全权证书设置如下:
HttpClientBuilder builder = HttpClientBuilder.create();
// Get the client credentials
String username = Config.get(Constants.CONFIG_USERNAME);
String password = Config.get(Constants.CONFIG_PASSWORD);
// If username and password was found, inject the credentials
if (username != null && password != null)
{
CredentialsProvider provider = new BasicCredentialsProvider();
// Create the authentication scope
AuthScope scope = new AuthScope(AuthScope.ANY_HOST, AuthScope.ANY_PORT, AuthScope.ANY_REALM);
// Create credential pair
UsernamePasswordCredentials credentials = new UsernamePasswordCredentials(username, password);
// Inject the credentials
provider.setCredentials(scope, credentials);
// Set the default credentials provider
builder.setDefaultCredentialsProvider(provider);
}
但是,这并不起作用(我正在使用的REST服务返回401)。出了什么问题?
5条答案
按热度按时间anhgbhbe1#
抢先认证文档如下:
http://hc.apache.org/httpcomponents-client-ga/tutorial/html/authentication.html
默认情况下,httpclient不会抢先提供凭据,它会首先创建一个没有身份验证参数的HTTP请求。这是设计的,作为安全预防措施,也是规范的一部分。但是,如果您不重试连接,或者您连接到的任何地方都希望您在第一次连接时发送身份验证详细信息,则会导致问题。它还导致请求的额外延迟,因为您需要进行多个调用,并导致401出现在日志中。
解决方法是使用身份验证缓存来假装您已经连接到服务器一次。这意味着你只会进行一次HTTP调用,并且不会在日志中看到401:
请注意:你需要信任你连接的主机,如果你使用HTTP,你的用户名和密码将以明文发送(好吧,base64,但这不算)。
您还应该使用更具体的Authscope,而不是像示例中那样依赖于
AuthScope .ANY_HOST
和AuthScope.ANY_PORT
。sh7euo9m2#
实际上,由于您已经信任服务器,因此自己构造授权头可能是最简单的。
这只是其中一种情况,它更容易阅读spec,并滚动它自己。
qyswt5oh3#
我刚刚尝试了你的代码示例(针对一个简单的启用了Basic Auth的URL),它工作得很好-这是来自
HttpClient
的日志-为了简洁起见,简化了一点:所以-简单地说:
HttpClient
识别基本身份验证方案并正确响应质询200 OK
您使用的REST服务可能实际上没有使用基本身份验证。您可以尝试粘贴完整的
HttpClient
日志以更好地诊断问题。希望能帮上忙。
8wtpewkr4#
我认为HttpClient就像其他基于curl的解决方案一样,它遵循规范。
规范是“除非服务器告诉你这样做,否则不要发送凭证”。所以你得到一个401(“我想让你发送凭据”)。
这是一个常见的soap ui问题:当你不知道的时候,
dldeef675#
对于使用apache http client 5的人来说,和我一样有同样的问题。
这些代码的灵感来自@Cetra,我添加了**initPreemptive()**来解决401问题。