4. Securing Spring
Эта глава охватывает:
Автоконфигурирование Spring Security
Определение пользовательского хранилища пользователя
Настройка страницы входа
Защита от CSRF-атак
Определение ваших пользователей
Вы когда-нибудь замечали, что большинство людей в телевизионных ситкомах не закрывают свои двери? Во времена Leave it to Beaver, не было ничего необычного в том, что люди оставляли свои двери незапертыми. Но кажется сумасшедшим, что в тот день, когда мы заботимся о конфиденциальности и безопасности, мы видим телевизионных персонажей, обеспечивающих беспрепятственный доступ к их квартирам и домам.
Информация, вероятно, самый ценный элемент, который мы сейчас имеем; мошенники ищут способы, чтобы украсть наши данные и идентичности, пробираясь в незащищенных приложений. Как разработчики программного обеспечения, мы должны принять меры для защиты информации, которая находится в наших приложениях. Является ли это учетной записью электронной почты, защищенной парой имени пользователя и пароля, или брокерским счетом, защищенным торговым PIN-кодом, безопасность является важным аспектом большинства приложений.
4.1 Включение Spring Security
Самым первым шагом в обеспечении безопасности приложения Spring является добавление зависимости Spring Boot security starter в сборку. В pom.xml файле, добавьте следующую запись
Если вы используете Spring Tool Suite, это еще проще. Щелкните правой кнопкой мыши на pom.xml файле и выберите Edit Starters из контекстного меню Spring. Откроется диалоговое окно Starter Dependencies. Выберите запись Security под категорией Core, как показано на рисунке 4.1.
Рис. 4.1 добавление стартер безопасности с Spring Tool Suite
Хотите верьте, хотите нет, но зависимость-это единственное, что требуется для защиты приложения. При запуске приложения автоконфигурация обнаружит, что Spring Security находится в пути к классам, и настроит базовую конфигурацию безопасности.
Если вы хотите попробовать, запустите приложение и попробуйте посетить домашнюю страницу (или любую другую страницу). Вам будет предложено выполнить проверку подлинности с помощью обычного HTTP диалогового окна. Чтобы пройти проверку, вам нужно будет предоставить имя пользователя и пароль. Имя пользователя user. Что касается пароля, то он генерируется случайным образом и записывается в файл журнала приложения. Запись журнала будет выглядеть примерно так:
Using default security password: 087cfc6a-027d-44bc-95d7-cbb3a798a1ea
Если вы введете имя пользователя и пароль правильно, вам будет предоставлен доступ к приложению.
Кажется, что обеспечение безопасности приложений Spring довольно простая работа. С защитой приложения Taco Cloud я полагаю, что закончено и я могу закончить эту главу сейчас и перейти к следующей теме. Но прежде чем мы забегаем вперед, давайте рассмотрим, какую автоконфигурацию безопасности мы обеспечили.
Не делая ничего, кроме добавления стартера безопасности в сборку проекта, вы получаете следующие функции безопасности:
-Все пути HTTP-запросов требуют аутентификации.
-Никаких конкретных ролей или полномочий не требуется.
-Нет страницы входа
-Проверка подлинности предлагается с обычной проверкой подлинности http.
-Есть только один пользователь; имя пользователя - user.
Это хорошее начало, но я думаю, что потребности в безопасности большинства приложений (включая Taco Cloud) будут сильно отличаться от этих элементарных функций безопасности.
От вас потребуется больше работы, если вы собираетесь правильно защитить приложение Taco Cloud. По крайней мере, необходимо настроить Spring Security для выполнения следующих действий:
-Запрашивать аутентификацию на странице входа, а не в диалоговом окне HTTP basic.
-Создать несколько пользователей и включить страницу регистрации, чтобы новые клиенты Taco Cloud могли зарегистрироваться.
-Применять различные правила безопасности для различных путей запроса. Например, домашняя страница и страницы регистрации вообще не должны требовать аутентификации.
Чтобы удовлетворить ваши потребности в безопасности для Taco Cloud, вам придется написать некоторую явную конфигурацию, переопределяя то, что дала вам автоконфигурация. Вы начнете с настройки надлежащего хранилища пользователей, чтобы иметь более одного пользователя.
4.2 Конфигурирование Spring Security
На протяжении многих лет существует несколько способов настройки Spring Security, включая долгую настройку на основе XML. К счастью, несколько последних версий Spring Security поддерживают конфигурацию на основе Java, которая намного проще для чтения и записи.
Прежде чем эта глава будет закончена, вы настроите все все параметры безопасности Taco Cloud на основаннии Java-based Spring Security конфигурации. Но чтобы начать работу, вы упростите ее, написав класс заготовки (-barebones) конфигурации, показанный в следующем листинге.
Листинг 4.1 Класс barebones конфигурации для Spring Security
package tacos.security;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
@Configuration
@EnableWebSecurity
public class SecurityConfig extends WebSecurityConfigurerAdapter {
}
Что делает эта barebones конфигурация для вас? Ну, не так много, но это делает вас на шаг ближе к функционалу безопасности который вам нужен. Если вы попытаетесь снова попасть на домашнюю страницу Taco Cloud, вам все равно будет предложено войти. Но вместо запроса диалогового окна обычной проверки подлинности HTTP вам будет показана форма входа в систему, как показано на рис. 4.2.
Рисунок 4.2 Spring Security дает вам простую страницу входа бесплатно.
TIP Переход в инкогнито: при ручном тестировании безопасности может оказаться полезным перевести браузер в частный режим или режим инкогнито. Это гарантирует, что у вас будет новая сессия каждый раз, когда вы открываете частное окно/инкогнито. Вам придется каждый раз входить в приложение, но вы можете быть уверены, что все изменения, внесенные в безопасность, будут применены, и что нет никаких остатков старого сеанса, которые не позволят вам увидеть ваши изменения.
Это небольшое улучшение-запрос на вход с веб-страницы (даже если это довольно просто по внешнему виду) всегда более удобно для пользователя, чем диалоговое окно HTTP basic. Вы настроите страницу входа в раздел 4.3.2. Однако текущей задачей является настройка хранилища пользователей, которое может обрабатывать более одного пользователя.
Как оказалось, Spring Security предлагает несколько вариантов настройки пользовательского хранилища, включая следующие:
-Хранилище пользователей в памяти
-Хранилище пользователей на основе JDBC
-Хранилище пользователей в LDAP
-Пользовательская (собственная) служба сведений о пользователе
Независимо от того, какое пользовательское хранилище выбрано, его можно настроить, переопределив метод configure(), определенный в базовом классе конфигурации WebSecurityConfigurerAdapter. Для начала добавьте в класс SecurityConfig следующее переопределение метода:
@Override
protected void configure(AuthenticationManagerBuilder auth) throws Exception {
...
}
Теперь вам просто нужно заменить эти многоточия с кодом, который использует данный AuthenticationManagerBuilder, чтобы указать, как пользователи будут авторизоваться (looked) во время аутентификации. Сначала вы реализуете хранилище пользователей в памяти.
4.2.1 Хранилище пользователей в памяти
Одно из мест, где пользовательская информация может храниться - это в памяти. Предположим, у вас есть только несколько пользователей, ни один из которых, скорее всего, не изменится. В этом случае может быть достаточно просто определить этих пользователей как часть конфигурации безопасности.
Листинг 4.2 Определение пользователей в хранилище пользователей в памяти
@Override
protected void configure(AuthenticationManagerBuilder auth) throws Exception {
auth.inMemoryAuthentication()
.withUser("buzz")
.password("infinity")
.authorities("ROLE_USER")
.and()
.withUser("woody")
.password("bullseye")
.authorities("ROLE_USER");
}
Как вы можете видеть, AuthenticationManagerBuilder использует builder-style API, чтобы настроить параметры проверки подлинности. В этом случае вызов метода inMemoryAuthentication() дает возможность указать сведения о пользователе непосредственно в самой конфигурации безопасности.
Каждый вызов withUser() запускает конфигурацию для пользователя. Значение, указанное в withUser() является имя пользователя, а пароль и полномочий указываются в методах password() и authorities(). Как показано в листинге 4.2, оба пользователя имеют права доступа ROLE_USER. Пользователь buzz настроен на infinity в качестве пароля. Аналогично, пароль woody -bullseye.
Хранилище пользователей в памяти удобно для тестирования или очень простых приложений, но оно не позволяет легко редактировать пользователей. Если необходимо добавить, удалить или изменить пользователя, необходимо внести необходимые изменения, а затем пересобрать и повторно развернуть приложение.
Для приложения Taco Cloud вы хотите, чтобы клиенты могли регистрироваться в приложении и управлять своими учетными записями пользователей. Это не соответствует ограничениям хранилища пользователей в памяти, поэтому давайте рассмотрим другой вариант, который позволяет использовать хранилище пользователей, поддерживаемое базой данных.