HttpClient Basic Authentication
1. обзор
В этом руководстве будет показано, какconfigure Basic Authentication on the Apache HttpClient 4.
Если вы хотите копнуть глубже и узнать о других интересных вещах, которые можно сделать с помощью HttpClient, перейдите кthe main HttpClient tutorial.
Дальнейшее чтение:
Учебник по HttpAsyncClient
HttpAsyncClient Tutorial - отправьте базовый запрос GET, используйте многопоточный клиент, настройте клиент с SSL и прокси и, наконец, выполните аутентификацию.
Расширенная настройка HttpClient
Конфигурации HttpClient для расширенных вариантов использования.
2. Базовая аутентификация с помощью API
Начнем сthe standard way of configuring Basic Authentication on the HttpClient – via a 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));
Как мы видим, создание клиента с провайдером учетных данных для его настройки с базовой аутентификацией не составляет труда.
Теперь, чтобы понять, что на самом деле будет делать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
ВесьClient-Server communication is now clear:
-
Клиент отправляет HTTP-запрос без учетных данных
-
Сервер отправляет обратно вызов
-
Клиент договаривается и определяет правильную схему аутентификации
-
Клиент отправляетa second Request, на этот раз с учетными данными
3. Упреждающая базовая аутентификация
По умолчаниюHttpClient не выполняет упреждающую аутентификацию. Вместо этого это должно быть явное решение, принятое клиентом.
Во-первых,we need to create the HttpContext – pre-populating it with an authentication cache с предварительно выбранным правильным типом схемы аутентификации. Это будет означать, что согласование из предыдущего примера больше не требуется -Basic Authentication is already chosen:
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);
Теперь мы можем использовать клиента с новым контекстом и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));
Посмотрим на журналы:
[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
Все выглядит хорошо:
-
схема «Базовая аутентификация» предварительно выбрана
-
Запрос отправляется с заголовкомAuthorization
-
Сервер отвечает200 OK
-
Аутентификация прошла успешно
4. Базовая аутентификация с необработанными заголовками HTTP
Вытесняющая базовая аутентификация в основном означает предварительную отправку заголовкаAuthorization.
Итак, вместо того, чтобы проходить довольно сложный предыдущий пример для его настройки,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));
Убедимся, что это работает правильно:
[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
Итак, даже если нет кеша аутентификации,Basic Authentication still works correctly and we receive 200 OK.
5. Заключение
В этой статье проиллюстрированы различные способы настройки и использования базовой аутентификации с помощью Apache HttpClient 4.
Как всегда, доступен код, представленный в этой статьеover on Github. Это проект, основанный на Maven, поэтому его легко импортировать и запускать как есть.