Сегодня мы переходим к практике — создадим базовое веб-приложение с настройкой Spring Security для защиты маршрутов и реализации аутентификации пользователей. Приготовьтесь к бою, друзья!
От построения приложения к добавлению безопасности
Цель и структура задачи
Прежде чем писать код, давайте представим, что мы создаем не просто приложение, а цифровой ресторан. Вам же нужно знать, кто пришел в гости (аутентификация) и куда их можно пустить (авторизация)? В обычном ресторане есть фейс-контроль и VIP-зоны, а в нашем приложении будет Spring Security.
Вот наш план действий:
- Создадим минимальное Spring Boot приложение — наш "ресторан"
- Добавим базовую защиту с помощью Spring Security — установим "двери и замки"
- Настроим систему проверки посетителей — кто вы и можно ли вам доверять?
- Определим правила доступа к разным зонам — кто куда может ходить
- Проверим нашу систему безопасности через браузер или Postman — устроим тестовый "визит"
Готовы построить самый безопасный цифровой ресторан? Давайте начнем!
Шаг 1: Создаём минималистичное Spring Boot приложение
Сначала создадим новый проект Spring Boot. Выбираем зависимости:
- Spring Web — чтобы наше приложение могло обрабатывать HTTP-запросы.
- Spring Security — собственно, для настройки безопасности.
Не забудьте добавить Gradle или Maven в вашем проекте. Например, для Maven ваш pom.xml будет выглядеть так:
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-security</artifactId>
</dependency>
</dependencies>
Теперь добавим простой контроллер.
@RestController
public class GreetingController {
@GetMapping("/public")
public String publicEndpoint() {
return "Этот эндпоинт доступен всем!";
}
@GetMapping("/secure")
public String secureEndpoint() {
return "Вы зашли в защищённую зону!";
}
}
Запустите приложение и попробуйте открыть маршруты /public и /secure. Обратите внимание, что Spring Security уже защищает весь ваш API. Попробуйте достучаться до /secure, и вы увидите браузерный экран логина. Это базовая защита, которую предоставляет Spring Security "из коробки".
Шаг 2: Настраиваем базовую конфигурацию
Теперь создадим кастомную настройку безопасности. Нам необходимо сделать так, чтобы:
/publicоставался открытым для всех./secureбыл защищён и доступен только аутентифицированным пользователям.
Создадим конфигурационный класс.
@EnableWebSecurity
public class SecurityConfig extends WebSecurityConfigurerAdapter {
@Override
protected void configure(HttpSecurity http) throws Exception {
http
.authorizeRequests()
.antMatchers("/public").permitAll() // Доступ открыт для всех
.anyRequest().authenticated() // Все остальные запросы требуют аутентификации
.and()
.formLogin() // Включаем стандартную форму логина
.and()
.httpBasic(); // Включаем HTTP Basic авторизацию
}
}
Запустите приложение заново. Теперь /public открывается без проблем, а доступ к /secure требует ввода имени пользователя и пароля через стандартную форму логина.
Шаг 3: Настройка пользователей
По умолчанию Spring Security использует предопределённого пользователя с именем user и случайным паролем, который отображается в логах приложения при запуске. Если вам надоело бегать глазами по логам в поисках пароля, давайте добавим собственных пользователей в application.properties.
spring.security.user.name=admin
spring.security.user.password=admin123
Теперь пользователь admin сможет аутентифицироваться с паролем admin123.
Но что, если нам нужно добавить разные роли (например, администраторов и обычных пользователей)? Давайте немного поднастроим систему.
Шаг 4: Добавляем авторизацию на основе ролей
Мы добавим две роли: ROLE_ADMIN и ROLE_USER. Для этого сначала обновим нашу конфигурацию безопасности:
@Override
protected void configure(HttpSecurity http) throws Exception {
http
.authorizeRequests()
.antMatchers("/public").permitAll()
.antMatchers("/secure").hasRole("ADMIN") // Доступ к /secure только для админов
.anyRequest().authenticated()
.and()
.formLogin()
.and()
.httpBasic();
}
Теперь создадим пользователей с разными ролями. Для этого переопределим метод configure в нашем классе SecurityConfig:
@Override
protected void configure(AuthenticationManagerBuilder auth) throws Exception {
auth.inMemoryAuthentication()
.withUser("admin").password(passwordEncoder().encode("admin123")).roles("ADMIN") // Админ
.and()
.withUser("user").password(passwordEncoder().encode("user123")).roles("USER"); // Обычный пользователь
}
@Bean
public PasswordEncoder passwordEncoder() {
return new BCryptPasswordEncoder();
}
Теперь у нас два пользователя:
adminс паролемadmin123и рольюROLE_ADMIN.userс паролемuser123и рольюROLE_USER.
И только администратор (admin) сможет получить доступ к /secure.
Шаг 5: Тестируем безопасность
Запустите приложение и протестируйте его:
- Откройте
/public— доступ открыт для всех. - Откройте
/secure— система запросит логин и пароль.- Введите
user/user123— получите отказ в доступе. - Введите
admin/admin123— получите доступ.
- Введите
Для тестирования также можно использовать Postman. Например, запрос к /secure можно отправить с Basic Auth, указав имя пользователя и пароль.
Шаг 6: Проверяем файл application.properties
Вот что можно добавить в application.properties для удобства:
# Логирование для отладки
logging.level.org.springframework.security=DEBUG
Так вы сможете видеть больше информации о том, как Spring Security обрабатывает ваши запросы.
Частые ошибки
- Ошибка: доступ к защищённым маршрутам предоставляется любому пользователю. Обычно это происходит из-за неправильно настроенных правил в
authorizeRequests. Проверьте порядок вызоваantMatchers— они обрабатываются сверху вниз. IllegalArgumentException: There is no PasswordEncoder mapped for ID "null". Это происходит, если вы забыли настроитьPasswordEncoder. Не забудьте добавить бинBCryptPasswordEncoderв ваш код, чтобы шифровать пароли.
Следующий шаг — внедрение хранения пользователей и ролей в базе данных, что мы рассмотрим в последующих лекциях. Куда же без интеграции с реальной базой, верно?
ПЕРЕЙДИТЕ В ПОЛНУЮ ВЕРСИЮ