HttpClientBuilder 基本身份验证 [英] HttpClientBuilder basic auth

查看:85
本文介绍了HttpClientBuilder 基本身份验证的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

从 HttpClient 4.3 开始,我一直在使用 HttpClientBuilder.我正在连接到具有基本身份验证的 REST 服务.我正在按如下方式设置凭据:

Since HttpClient 4.3, I have been using the HttpClientBuilder. I am connecting to a REST service that has basic authentication. I am setting the credentials as follows:

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).出了什么问题?

However, this does not work (the REST service that I am using is returning 401). What is going wrong?

推荐答案

来自 Preemptive Authentication 文档:

http://hc.apache.org/httpcomponents-client-ga/tutorial/html/authentication.html

默认情况下,httpclient 不会抢先提供凭据,它会先创建一个没有身份验证参数的 HTTP 请求.这是设计使然,作为安全预防措施,并且作为规范的一部分.但是,如果您不重试连接,或者您连接到的任何地方都希望您在第一次连接时发送身份验证详细信息,则会导致问题.它还会给请求造成额外的延迟,因为您需要进行多次调用,并导致 401 出现在日志中.

By default, httpclient will not provide credentials preemptively, it will first create a HTTP request without authentication parameters. This is by design, as a security precaution, and as part of the spec. But, this causes issues if you don't retry the connection, or wherever you're connecting to expects you to send authentication details on the first connection. It also causes extra latency to a request, as you need to make multiple calls, and causes 401s to appear in the logs.

解决方法是使用身份验证缓存来假装您已经连接到服务器一次.这意味着您只会进行一次 HTTP 调用,并且不会在日志中看到 401:

The workaround is to use an authentication cache to pretend that you've already connected to the server once. This means you'll only make one HTTP call and won't see a 401 in the logs:

CloseableHttpClient httpclient = HttpClientBuilder.create().build();

HttpHost targetHost = new HttpHost("localhost", 80, "http");
CredentialsProvider credsProvider = new BasicCredentialsProvider();
credsProvider.setCredentials(
        new AuthScope(targetHost.getHostName(), targetHost.getPort()),
        new UsernamePasswordCredentials("username", "password"));

// Create AuthCache instance
AuthCache authCache = new BasicAuthCache();
// Generate BASIC scheme object and add it to the local auth cache
BasicScheme basicAuth = new BasicScheme();
authCache.put(targetHost, basicAuth);

// Add AuthCache to the execution context
HttpClientContext context = HttpClientContext.create();
context.setCredentialsProvider(credsProvider);
context.setAuthCache(authCache);

HttpGet httpget = new HttpGet("/");
for (int i = 0; i < 3; i++) {
    CloseableHttpResponse response = httpclient.execute(
            targetHost, httpget, context);
    try {
        HttpEntity entity = response.getEntity();

    } finally {
        response.close();
    }
}

请注意:您需要信任您正在连接的主机,如果您使用 HTTP,您的用户名和密码将以明文形式发送(好吧,base64,但这不算数).

Please note: You need to trust the host you're connecting to, and if you're using HTTP, your username and password will be sent in cleartext (well, base64, but that doesn't count).

您还应该使用更具体的 Authscope,而不是像示例中那样依赖 AuthScope .ANY_HOSTAuthScope.ANY_PORT.

You should also be using a much more specific Authscope rather than relying on AuthScope .ANY_HOST and AuthScope.ANY_PORT like in your example.

这篇关于HttpClientBuilder 基本身份验证的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆