Автор оригинала: Eugen Paraschiv.
1. Обзор
В этом руководстве будет показано, как настроить базовую аутентификацию на Apache HttpClient 4 .
Если вы хотите копнуть глубже и узнать другие интересные вещи, которые вы можете сделать с помощью HttpClient – перейдите к основному учебнику HttpClient .
Дальнейшее чтение:
Учебник HttpAsyncClient
Расширенная конфигурация HttpClient
2. Базовая аутентификация С помощью API
Давайте начнем с стандартного способа настройки базовой аутентификации на 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));
Как мы видим, создание клиента с поставщиком учетных данных для настройки его с помощью базовой аутентификации не составляет труда.
Теперь, чтобы понять, что на самом деле будет делать 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 – предварительно заполнив его кэшем аутентификации с предварительно выбранным правильным типом схемы аутентификации. Это будет означать, что согласование из предыдущего примера больше не требуется – Базовая аутентификация уже выбрана :
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);
Теперь мы можем использовать клиент с новым контекстом и отправить запрос на предварительную аутентификацию :
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 .
Таким образом, вместо того, чтобы проходить довольно сложный предыдущий пример, чтобы настроить его, мы можем взять под контроль этот заголовок и построить его вручную :
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
Таким образом, даже несмотря на отсутствие кэша аутентификации, Базовая аутентификация по-прежнему работает правильно, и мы получаем 200 OK.
5. Заключение
В этой статье проиллюстрированы различные способы настройки и использования базовой аутентификации с помощью Apache HttpClient 4.
Как всегда, код, представленный в этой статье, доступен на Github . Это проект на основе Maven, поэтому его должно быть легко импортировать и запускать как есть.