Целевая аудитория: разработчики, знакомые с основами Spring Boot и Java 11, но впервые сталкивающиеся с Spring Security.
Цель статьи: дать понимание, как Spring Security защищает веб-приложение, и показать минимальный, но рабочий пример с пояснениями.
1. Что такое Spring Security?
Spring Security — это мощный и гибкий фреймворк для аутентификации и авторизации в приложениях на базе Spring. Он позволяет:
- Ограничить доступ к URL-адресам или методам;
- Поддерживать различные способы входа (форма, HTTP Basic, OAuth2, LDAP и т.д.);
- Защищать от распространённых уязвимостей: CSRF, XSS, clickjacking и др.;
- Интегрировать пользовательские источники аутентификации.
2. Подготовка проекта
Для начала создадим простое Spring Boot-приложение.
Требования: Java 11, Maven (или Gradle), Spring Boot ≥ 2.7.
Зависимости (Maven)
<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>
💡 При добавлении spring-boot-starter-security Spring Boot автоматически:
- Защитит все HTTP-эндпоинты;
- Создаст пользователя по умолчанию с именем user и случайным паролем (отображается в логах при запуске).
3. Простейший контроллер
Создадим контроллер, который вернёт HTML-страницу:
Мы будем использовать Thymeleaf, поэтому добавьте зависимость:
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-thymeleaf</artifactId>
</dependency>
4. Базовая конфигурация безопасности
Создадим класс конфигурации:
Объяснение ключевых моментов:
Конструкция
Что делает
authorizeHttpRequests
Задаёт правила доступа к URL
.permitAll()
Полный доступ без аутентификации
.hasRole("ADMIN")
Требует роль ROLE_ADMIN (Spring автоматически добавляет префикс ROLE_)
formLogin()
Включает форму входа по URL /login
InMemoryUserDetailsManager
Хранилище пользователей в памяти (не для продакшена!)
{noop}
Указывает, что пароль не зашифрован. В реальных проектах обязательно используйте PasswordEncoder
⚠️ Никогда не используйте {noop} в продакшене!
Вместо этого внедрите PasswordEncoder:
@Bean
public PasswordEncoder passwordEncoder() {
return new BCryptPasswordEncoder();
}
5. Thymeleaf-шаблоны
Создадим простые HTML-файлы в src/main/resources/templates/:
login.html
<!DOCTYPE html>
<html xmlns:th="http://www.thymeleaf.org">
<head><title>Login</title></head>
<body>
<h2>Вход в систему</h2>
<form th:action="@{/login}" method="post">
<div>
<label>Имя пользователя:</label>
<input type="text" name="username" />
</div>
<div>
<label>Пароль:</label>
<input type="password" name="password" />
</div>
<button type="submit">Войти</button>
</form>
<!-- Сообщение об ошибке -->
<div th:if="${param.error}">
Неверное имя или пароль!
</div>
</div>
</body>
</html>
home.html
<!DOCTYPE html>
<html xmlns:th="http://www.thymeleaf.org"
xmlns:sec="http://www.thymeleaf.org/extras/spring-security">
<head><title>Главная</title></head>
<body>
<h1>Добро пожаловать!</h1>
<p>Вы вошли как: <span sec:authentication="name"></span></p>
<div sec:authorize="hasRole('ADMIN')">
<a href="/admin">Панель администратора</a>
</div>
<a href="/public">Публичная страница</a> |
<a href="/logout">Выйти</a>
</body>
</html>
💡 Для работы sec: атрибутов добавьте зависимость:
<dependency>
<groupId>org.thymeleaf.extras</groupId>
<artifactId>thymeleaf-extras-springsecurity5</artifactId>
</dependency>
6. Как это работает под капотом?
Spring Security использует цепочку фильтров (Filter Chain), которая обрабатывает каждый HTTP-запрос до достижения контроллера.
Ключевые фильтры (упрощённо):
- SecurityContextPersistenceFilter — загружает контекст безопасности;
- UsernamePasswordAuthenticationFilter — обрабатывает форму входа;
- FilterSecurityInterceptor — проверяет права доступа к URL.
Если пользователь не авторизован и пытается зайти на защищённый URL — его перенаправляют на /login.
7. Проверка работы
Запустите приложение (mvn spring-boot:run). Откройте в браузере:
- http://localhost:8080/ → перенаправит на /login
- Введите: user / password → попадёте на главную
- Попробуйте зайти на /admin → доступ запрещён
- Выйдите и войдите как admin / admin → /admin доступен
8. Что дальше?
После освоения базы вы можете:
- ✅ Использовать базу данных вместо InMemoryUserDetailsManager;
- ✅ Настроить шифрование паролей через BCryptPasswordEncoder;
- ✅ Интегрировать OAuth2 (Google, GitHub и др.);
- ✅ Добавить метод-level security через @PreAuthorize;
- ✅ Настроить CORS, CSRF-защиту, rate limiting.
Заключение
Spring Security может показаться сложным на первый взгляд, но его базовая настройка занимает всего несколько строк. Главное — понять логику: "кто может что делать?". После этого вы сможете гибко управлять доступом в своём приложении, будучи уверенным в его безопасности.