Найти в Дзене

Базовая аутентификация Apache HttpClient

1. Общий обзор В этом руководстве будет показано, как настроить базовую аутентификацию в Apache HttpClient 5. 2. Базовая аутентификация с помощью API Давайте начнем со стандартного способа настройки базовой аутентификации на HttpClient – через CredentialsProvider: final HttpHost targetHost = new HttpHost("http", "localhost", 8082);
final BasicCredentialsProvider provider = new BasicCredentialsProvider();
AuthScope authScope = new AuthScope(targetHost);
provider.setCredentials(authScope, new UsernamePasswordCredentials(DEFAULT_USER, DEFAULT_PASS_ARRAY));
final HttpGet request = new HttpGet(URL_SECURED_BY_BASIC_AUTHENTICATION);
try (CloseableHttpClient client = HttpClientBuilder.create()
.setDefaultCredentialsProvider(provider())
.build();
CloseableHttpResponse response = (CloseableHttpResponse) client
.execute(request, new CustomHttpClientResponseHandler())) {
final int statusCode = response.getCode();
assertThat(statusCode, equalTo(HttpStatus.SC_OK));
}
Оглавление

1. Общий обзор

В этом руководстве будет показано, как настроить базовую аутентификацию в Apache HttpClient 5.

2. Базовая аутентификация с помощью API

Давайте начнем со стандартного способа настройки базовой аутентификации на HttpClient – через CredentialsProvider:

final HttpHost targetHost = new HttpHost("http", "localhost", 8082);
final BasicCredentialsProvider provider = new BasicCredentialsProvider();
AuthScope authScope = new AuthScope(targetHost);
provider.setCredentials(authScope, new UsernamePasswordCredentials(DEFAULT_USER, DEFAULT_PASS_ARRAY));

final HttpGet request = new HttpGet(URL_SECURED_BY_BASIC_AUTHENTICATION);

try (CloseableHttpClient client = HttpClientBuilder.create()
.setDefaultCredentialsProvider(provider())
.build();

CloseableHttpResponse response = (CloseableHttpResponse) client
.execute(request, new CustomHttpClientResponseHandler())) {
final int statusCode = response.getCode();
assertThat(statusCode, equalTo(HttpStatus.SC_OK));
}

Как мы видим, создать клиент с поставщиком учетных данных для настройки базовой аутентификации несложно.

Теперь, чтобы понять, что на самом деле будет делать 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

Теперь все взаимодействие между клиентом и сервером стало понятным:

  • клиент отправляет HTTP-запрос без каких-либо учетных данных
  • сервер отправляет ответный запрос
  • клиент согласовывает и определяет правильную схему аутентификации
  • Клиент отправляет второй запрос, на этот раз с учетными данными

3. Предварительная базовая аутентификация

Изначально HttpClient не выполняет превентивную аутентификацию. Вместо этого это должно быть явное решение, принятое клиентом.

Сначала
нам нужно создать HttpContext, предварительно заполнив его кэшем аутентификации с предварительно выбранным типом схемы аутентификации. Это будет означать, что согласование из предыдущего примера больше не требуется – базовая аутентификация уже выбрана:

final HttpHost targetHost = new HttpHost("http", "localhost", 8082);
final BasicCredentialsProvider credsProvider = new BasicCredentialsProvider();
AuthScope authScope = new AuthScope(targetHost);
credsProvider.setCredentials(authScope, new UsernamePasswordCredentials(DEFAULT_USER, DEFAULT_PASS_ARRAY));

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

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

Теперь мы можем использовать клиент с новым контекстом и отправить запрос на предварительную аутентификацию:

final HttpGet request = new HttpGet(URL_SECURED_BY_BASIC_AUTHENTICATION);
try (CloseableHttpClient client = HttpClientBuilder.create()
.build();

CloseableHttpResponse response = (CloseableHttpResponse) client
.execute(request, context(), new CustomHttpClientResponseHandler())) {
final int statusCode = response.getCode();
assertThat(statusCode, equalTo(200));
}

Давайте посмотрим на логи:

[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

Все выглядит нормально:

  • предварительно выбрана схема “Базовой аутентификации”
  • запрос отправляется с заголовком авторизации
  • сервер отвечает 200 OK
  • Проверка подлинности прошла успешно

4. Базовая аутентификация с необработанными HTTP-заголовками

Предварительная аутентификация по умолчанию означает предварительную отправку заголовка авторизации.

Таким образом, вместо того, чтобы использовать довольно сложный предыдущий пример для его настройки,
мы можем взять под контроль этот заголовок и создать его вручную:

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

try (CloseableHttpClient client = HttpClientBuilder.create()
.build();

CloseableHttpResponse response = (CloseableHttpResponse) client
.execute(request, new CustomHttpClientResponseHandler())) {
final int statusCode = response.getCode();
assertThat(statusCode, equalTo(HttpStatus.SC_OK));
}

Давайте убедимся, что это работает правильно:

[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

Таким образом, несмотря на отсутствие кэша аутентификации, базовая аутентификация по-прежнему работает корректно, и мы получаем 200 OK.

5. Заключение

В этой статье проиллюстрированы различные способы настройки и использования базовой аутентификации с помощью Apache HttpClient.

Оригинал статьи: https://www.baeldung.com/httpclient-basic-authentication