HttpClientBuilder基本身份验证

Say*_*jee 17 java apache basic-authentication apache-httpclient-4.x

自从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);
}
Run Code Online (Sandbox Code Playgroud)

但是,这不起作用(我正在使用的REST服务返回401).出了什么问题?

Cet*_*tra 37

从这里的抢先身份验证文档:

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

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

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

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();
    }
}
Run Code Online (Sandbox Code Playgroud)

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

你也应该使用一个更具体的Authscope而不是依赖AuthScope .ANY_HOSTAuthScope.ANY_PORT喜欢你的榜样.


use*_*221 17

实际上,由于您已经信任服务器,因此最简单的方法就是自己构建授权头.

 byte[] credentials = Base64.encodeBase64((username + ":" + password).getBytes(StandardCharsets.UTF_8));
 request.setHeader("Authorization", "Basic " + new String(credentials, StandardCharsets.UTF_8));
 httpClient.execute(request);
Run Code Online (Sandbox Code Playgroud)

这只是其中一种情况,因为它更容易阅读规范,并自己滚动.