Apache HttpClient Basic Authentication – Apache HttpClient基本认证

最后修改: 2014年 1月 31日

中文/混合/英文(键盘快捷键:t)

1. Overview

1.概述

This tutorial will illustrate how to configure Basic Authentication on the Apache HttpClient.

本教程将说明如何在Apache HttpClient上配置基本认证

If you want to dig deeper and learn other cool things you can do with the HttpClient – head on over to the main HttpClient tutorial.

如果你想更深入地了解你可以用HttpClient做的其他很酷的事情–请到主要HttpClient教程

2. Basic Authentication With the API

2.用API进行基本认证

Let’s start with the standard way of configuring Basic Authentication on the HttpClient – via a CredentialsProvider:

让我们从在HttpClient上配置基本认证的标准方式开始 – 通过CredentialsProvider

CredentialsProvider provider = new BasicCredentialsProvider();
UsernamePasswordCredentials credentials
 = new UsernamePasswordCredentials("user1", "user1Pass");
provider.setCredentials(AuthScope.ANY, credentials);
 
HttpClient client = HttpClientBuilder.create()
  .setDefaultCredentialsProvider(provider)
  .build();

HttpResponse response = client.execute(
  new HttpGet(URL_SECURED_BY_BASIC_AUTHENTICATION));
int statusCode = response.getStatusLine()
  .getStatusCode();
 
assertThat(statusCode, equalTo(HttpStatus.SC_OK));

As we can see, creating the client with a credentials provider to set it up with Basic Authentication is not difficult.

正如我们所看到的,用凭证提供者创建客户端来设置基本认证并不困难。

Now, to understand what HttpClient will actually do behind the scenes, we’ll need to look at the logs:

现在,为了了解HttpClient在幕后究竟会做什么,我们需要看一下日志。

# ... request is sent with no credentials
[main] DEBUG ... - Authentication required
[main] DEBUG ... - localhost:8080 requested authentication
[main] DEBUG ... - Authentication schemes in the order of preference: 
  [negotiate, Kerberos, NTLM, Digest, Basic]
[main] DEBUG ... - Challenge for negotiate authentication scheme not available
[main] DEBUG ... - Challenge for Kerberos authentication scheme not available
[main] DEBUG ... - Challenge for NTLM authentication scheme not available
[main] DEBUG ... - Challenge for Digest authentication scheme not available
[main] DEBUG ... - Selected authentication options: [BASIC]
# ... the request is sent again - with credentials

The entire Client-Server communication is now clear:

整个客户端-服务器通信现在很清楚

  • the Client sends the HTTP Request with no credentials
  • the Server sends back a challenge
  • the Client negotiates and identifies the right authentication scheme
  • the Client sends a second Request, this time with credentials

3. Preemptive Basic Authentication

3.先发制人的基本认证

Out of the box, the HttpClient doesn’t do preemptive authentication. Instead, this has to be an explicit decision made by the client.

开箱即用的HttpClient并不做抢先认证。相反,这必须是一个由客户端做出的明确决定。

First, we need to create the HttpContext – pre-populating it with an authentication cache with the right type of authentication scheme pre-selected. This will mean that the negotiation from the previous example is no longer necessary – Basic Authentication is already chosen:

首先,我们需要创建HttpContext–预先用认证缓存填充它,预先选择正确的认证方案类型。这意味着前面的例子中的协商不再需要了–基本认证已经被选中了

HttpHost targetHost = new HttpHost("localhost", 8082, "http");
CredentialsProvider credsProvider = new BasicCredentialsProvider();
credsProvider.setCredentials(AuthScope.ANY, 
  new UsernamePasswordCredentials(DEFAULT_USER, DEFAULT_PASS));

AuthCache authCache = new BasicAuthCache();
authCache.put(targetHost, new BasicScheme());

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

Now we can use the client with the new context and send the pre-authentication request:

现在我们可以使用带有新上下文的客户端,发送预认证请求

HttpClient client = HttpClientBuilder.create().build();
response = client.execute(
  new HttpGet(URL_SECURED_BY_BASIC_AUTHENTICATION), context);

int statusCode = response.getStatusLine().getStatusCode();
assertThat(statusCode, equalTo(HttpStatus.SC_OK));

Let’s look at the logs:

让我们看一下日志。

[main] DEBUG ... - Re-using cached 'basic' auth scheme for http://localhost:8082
[main] DEBUG ... - Executing request GET /spring-security-rest-basic-auth/api/foos/1 HTTP/1.1
[main] DEBUG ... >> GET /spring-security-rest-basic-auth/api/foos/1 HTTP/1.1
[main] DEBUG ... >> Host: localhost:8082
[main] DEBUG ... >> Authorization: Basic dXNlcjE6dXNlcjFQYXNz
[main] DEBUG ... << HTTP/1.1 200 OK
[main] DEBUG ... - Authentication succeeded

Everything looks OK:

一切看起来都很好。

  • the “Basic Authentication” scheme is pre-selected
  • the Request is sent with the Authorization header
  • the Server responds with a 200 OK
  • Authentication succeeds

4. Basic Auth With Raw HTTP Headers

4.使用原始HTTP头的基本认证

Preemptive Basic Authentication basically means pre-sending the Authorization header.

预先基本认证基本上意味着预先发送Authorization头。

So, instead of going through the rather complex previous example to set it up, we can take control of this header and construct it by hand:

因此,与其通过前面相当复杂的例子来设置它,我们可以控制这个头,用手来构建它

HttpGet request = new HttpGet(URL_SECURED_BY_BASIC_AUTHENTICATION);
String auth = DEFAULT_USER + ":" + DEFAULT_PASS;
byte[] encodedAuth = Base64.encodeBase64(
  auth.getBytes(StandardCharsets.ISO_8859_1));
String authHeader = "Basic " + new String(encodedAuth);
request.setHeader(HttpHeaders.AUTHORIZATION, authHeader);

HttpClient client = HttpClientBuilder.create().build();
HttpResponse response = client.execute(request);

int statusCode = response.getStatusLine().getStatusCode();
assertThat(statusCode, equalTo(HttpStatus.SC_OK));

Let’s make sure this is working correctly:

让我们确保这个工作是正确的。

[main] DEBUG ... - Auth cache not set in the context
[main] DEBUG ... - Opening connection {}->http://localhost:8080
[main] DEBUG ... - Connecting to localhost/127.0.0.1:8080
[main] DEBUG ... - Executing request GET /spring-security-rest-basic-auth/api/foos/1 HTTP/1.1
[main] DEBUG ... - Proxy auth state: UNCHALLENGED
[main] DEBUG ... - http-outgoing-0 >> GET /spring-security-rest-basic-auth/api/foos/1 HTTP/1.1
[main] DEBUG ... - http-outgoing-0 >> Authorization: Basic dXNlcjE6dXNlcjFQYXNz
[main] DEBUG ... - http-outgoing-0 << HTTP/1.1 200 OK

So, even though there is no auth cache, Basic Authentication still works correctly and we receive 200 OK.

因此,即使没有 auth 缓存,基本认证仍能正常工作,我们收到200 OK.

5. Conclusion

5.结论

This article illustrated various ways to set up and use basic authentication with the Apache HttpClient.

这篇文章说明了用Apache HttpClient设置和使用基本认证的各种方法。

As always, the code presented in this article is available over on Github. This is a Maven based project, so it should be easy to import and run as it is.

一如既往,本文介绍的代码可在Github上找到。这是一个基于Maven的项目,所以应该很容易导入并按原样运行。