«Содержание

    1. Обзор 2. Настройка базовой аутентификации 2.1. Удовлетворение ограничения без сохранения состояния — избавление от сеансов 3. Настройка дайджест-аутентификации 4. Поддержка обоих протоколов аутентификации в одной службе RESTful 4.1. Анонимный запрос 4.2. Запрос с учетными данными аутентификации 5. Тестирование обоих сценариев 6. Заключение

1. Обзор

В этой статье обсуждается, как настроить обычную и дайджест-аутентификацию в одной и той же структуре URI REST API. В предыдущей статье мы обсуждали другой метод защиты службы REST — аутентификацию на основе форм, поэтому обычная и дайджест-аутентификация являются естественной альтернативой, а также более RESTful.

2. Настройка базовой аутентификации

Основная причина того, что аутентификация на основе форм не идеальна для службы RESTful, заключается в том, что Spring Security будет использовать сеансы — это, конечно, состояние на сервере, поэтому ограничения безгражданства в REST практически игнорируются.

Мы начнем с настройки базовой аутентификации — сначала мы удалим старую пользовательскую точку входа и фильтр из основного элемента безопасности \u003chttp\u003e:

<http create-session="stateless">
   <intercept-url pattern="/api/admin/**" access="ROLE_ADMIN" />

   <http-basic />
</http>

Обратите внимание, что поддержка базовой аутентификации была добавлена ​​с помощью единственная строка конфигурации — \u003chttp-basic /\u003e — которая обрабатывает создание и подключение как BasicAuthenticationFilter, так и BasicAuthenticationEntryPoint.

2.1. Удовлетворение ограничения без сохранения состояния — избавление от сеансов

Одним из основных ограничений архитектурного стиля RESTful является то, что взаимодействие клиент-сервер полностью не имеет состояния, как гласит исходная диссертация:

5.1.3 Stateless

We next add a constraint to the client-server interaction: communication must be stateless in nature, as in the client-stateless-server (CSS) style of Section 3.4.3 (Figure 5-3), such that each request from client to server must contain all of the information necessary to understand the request, and cannot take advantage of any stored context on the server. Session state is therefore kept entirely on the client.

Концепция сеанса на server имеет долгую историю в Spring Security, и до сих пор полностью удалить его было сложно, особенно когда конфигурация выполнялась с использованием пространства имен.

Однако Spring Security дополняет конфигурацию пространства имен новой опцией без сохранения состояния для создания сеанса, которая эффективно гарантирует, что Spring не будет создавать или использовать сеанс. Эта новая опция полностью удаляет все фильтры, связанные с сеансом, из цепочки фильтров безопасности, гарантируя, что аутентификация выполняется для каждого запроса.

3. Настройка дайджест-аутентификации

Начиная с предыдущей конфигурации, фильтр и точка входа, необходимые для настройки дайджест-аутентификации, будут определены как bean-компоненты. Затем точка входа дайджеста переопределит точку входа, созданную \u003chttp-basic\u003e за кулисами. Наконец, настраиваемый дайджест-фильтр будет введен в цепочку фильтров безопасности с использованием семантики after пространства имен безопасности, чтобы расположить его непосредственно после основного фильтра проверки подлинности.

<http create-session="stateless" entry-point-ref="digestEntryPoint">
   <intercept-url pattern="/api/admin/**" access="ROLE_ADMIN" />

   <http-basic />
   <custom-filter ref="digestFilter" after="BASIC_AUTH_FILTER" />
</http>

<beans:bean id="digestFilter" class=
 "org.springframework.security.web.authentication.www.DigestAuthenticationFilter">
   <beans:property name="userDetailsService" ref="userService" />
   <beans:property name="authenticationEntryPoint" ref="digestEntryPoint" />
</beans:bean>

<beans:bean id="digestEntryPoint" class=
 "org.springframework.security.web.authentication.www.DigestAuthenticationEntryPoint">
   <beans:property name="realmName" value="Contacts Realm via Digest Authentication"/>
   <beans:property name="key" value="acegi" />
</beans:bean>

<authentication-manager>
   <authentication-provider>
      <user-service id="userService">
         <user name="eparaschiv" password="eparaschiv" authorities="ROLE_ADMIN" />
         <user name="user" password="user" authorities="ROLE_USER" />
      </user-service>
   </authentication-provider>
</authentication-manager>

К сожалению, в пространстве имен безопасности нет поддержки для автоматической настройки дайджест-аутентификации так, как можно настроить обычную аутентификацию с помощью \u003chttp-basic\u003e. Из-за этого необходимые bean-компоненты должны были быть определены и вручную подключены к конфигурации безопасности.

4. Поддержка обоих протоколов аутентификации в одной и той же службе Restful

Только базовая или дайджест-аутентификация может быть легко реализована в Spring Security; он поддерживает оба из них для одной и той же веб-службы RESTful с одними и теми же сопоставлениями URI, что вводит новый уровень сложности в настройку и тестирование службы.

4.1. Анонимный запрос

Как с базовыми, так и с дайджест-фильтрами в цепочке безопасности способ анонимного запроса — запрос, не содержащий учетных данных аутентификации (HTTP-заголовок авторизации) — обрабатывается Spring Security — две аутентификации фильтры не найдут учетных данных и продолжат выполнение цепочки фильтров. Затем, видя, что запрос не был аутентифицирован, выдается исключение AccessDeniedException, которое перехватывается в ExceptionTranslationFilter, который запускает точку входа дайджеста, запрашивая у клиента учетные данные.

«Обязанности как основного, так и дайджест-фильтра очень узкие — они будут продолжать выполнять цепочку фильтров безопасности, если не смогут идентифицировать тип учетных данных аутентификации в запросе. Именно поэтому Spring Security может гибко настраивать поддержку нескольких протоколов аутентификации для одного и того же URI.

Когда делается запрос, содержащий правильные учетные данные для аутентификации — базовые или дайджест — этот протокол будет использоваться правильно. Однако для анонимного запроса клиенту будет предложено ввести только учетные данные дайджест-аутентификации. Это связано с тем, что точка входа дайджеста настроена как основная и единственная точка входа в цепочку Spring Security; поскольку такая дайджест-аутентификация может считаться используемой по умолчанию.

4.2. Запрос с учетными данными аутентификации

Запрос с учетными данными для базовой аутентификации будет идентифицирован по заголовку авторизации, начинающемуся с префикса «Basic». При обработке такого запроса учетные данные будут декодированы в фильтре базовой аутентификации, и запрос будет авторизован. Точно так же запрос с учетными данными для дайджест-аутентификации будет использовать префикс «дайджест» для заголовка авторизации.

5. Тестирование обоих сценариев

Тесты будут использовать службу REST, создавая новый ресурс после аутентификации с помощью базовой или дайджест-аутентификации:

@Test
public void givenAuthenticatedByBasicAuth_whenAResourceIsCreated_then201IsReceived(){
   // Given
   // When
   Response response = given()
    .auth().preemptive().basic( ADMIN_USERNAME, ADMIN_PASSWORD )
    .contentType( HttpConstants.MIME_JSON ).body( new Foo( randomAlphabetic( 6 ) ) )
    .post( paths.getFooURL() );

   // Then
   assertThat( response.getStatusCode(), is( 201 ) );
}
@Test
public void givenAuthenticatedByDigestAuth_whenAResourceIsCreated_then201IsReceived(){
   // Given
   // When
   Response response = given()
    .auth().digest( ADMIN_USERNAME, ADMIN_PASSWORD )
    .contentType( HttpConstants.MIME_JSON ).body( new Foo( randomAlphabetic( 6 ) ) )
    .post( paths.getFooURL() );

   // Then
   assertThat( response.getStatusCode(), is( 201 ) );
}

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

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

В этой статье были рассмотрены настройка и реализация как базовой, так и дайджест-аутентификации для службы RESTful с использованием в основном поддержки пространства имен Spring Security, а также некоторых новых функций в фреймворке.