В мире веб-приложений пользователи — это не просто абстрактные "люди". Каждому пользователю может быть присвоена роль, определяющая, какие действия он может выполнять. Это важный аспект безопасности, поскольку обеспечивает строгое разделение доступа к данным и функционалу.
Представьте, что вы разрабатываете банковское приложение: клиент может видеть свои счета, переводить средства, но не может, например, генерировать банковские отчёты. А вот администратор может. Чтобы управлять этим разделением на уровне кода, используется роль-ориентированная система доступа. В Spring Security это делается с помощью аннотации @Secured.
Аннотация @Secured позволяет настроить доступ к методам или ресурсам на основании ролей пользователей. Её можно использовать для ограничения доступа на уровне сервисов, контроллеров или даже отдельных бизнес-методов.
Официальная документация: Spring Security: @Secured
Настройка роли и безопасности с использованием @Secured
Давайте разбираться с этим шаг за шагом.
1. Настройка проекта
Создадим простое Spring Boot-приложение, где будем работать с пользователями и ролями. Убедитесь, что у вас есть активный Spring Security.
Добавляем зависимости в pom.xml
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-security</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-jpa</artifactId>
</dependency>
<dependency>
<groupId>com.h2database</groupId>
<artifactId>h2</artifactId>
<scope>runtime</scope>
</dependency>
Конфигурация безопасности
Для применения @Secured нужно включить поддержку безопасности на уровне методов.
import org.springframework.context.annotation.Configuration;
import org.springframework.security.config.annotation.method.configuration.EnableGlobalMethodSecurity;
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
@Configuration
@EnableWebSecurity
@EnableGlobalMethodSecurity(securedEnabled = true) // Включаем поддержку @Secured
public class SecurityConfig {
// В этой лекции используется встроенная конфигурация пользователя (InMemoryUserDetailsManager),
// Более сложные примеры с базой данных разберем позже.
}
2. Определяем роли и пользователей
Для тестирования создадим роли и пользователей в памяти (InMemoryUserDetailsManager).
Задаём пользователей и роли:
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.core.userdetails.User;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.security.provisioning.InMemoryUserDetailsManager;
@Configuration
public class UserConfig {
@Bean
public InMemoryUserDetailsManager userDetailsManager() {
UserDetails admin = User.builder()
.username("admin")
.password(passwordEncoder().encode("admin123"))
.roles("ADMIN") // Роль администратора
.build();
UserDetails user = User.builder()
.username("user")
.password(passwordEncoder().encode("user123"))
.roles("USER") // Роль пользователя
.build();
return new InMemoryUserDetailsManager(admin, user);
}
@Bean
public PasswordEncoder passwordEncoder() {
return new BCryptPasswordEncoder(); // Шифруем пароли
}
}
3. Использование @Secured в сервисах
Создадим простой сервис и ограничим доступ к его методам на основании ролей.
Реализуем сервис:
import org.springframework.security.access.annotation.Secured;
import org.springframework.stereotype.Service;
@Service
public class MyService {
@Secured("ROLE_ADMIN") // Доступ только для администраторов
public String adminMethod() {
return "Привет, Администратор!";
}
@Secured("ROLE_USER") // Доступ только для пользователей
public String userMethod() {
return "Привет, Пользователь!";
}
}
Обратите внимание, что роли должны быть указаны с префиксом ROLE_. Например, ROLE_ADMIN. Это стандарт Spring Security.
4. Создаём контроллер для тестирования
Теперь создадим REST-контроллер, который будет использовать наш сервис.
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;
@RestController
public class MyController {
private final MyService myService;
public MyController(MyService myService) {
this.myService = myService;
}
@GetMapping("/admin")
public String adminEndpoint() {
return myService.adminMethod();
}
@GetMapping("/user")
public String userEndpoint() {
return myService.userMethod();
}
}
5. Тестируем приложение
Запускаем приложение и тестируем:
- Откройте Postman или просто браузер.
- Попробуйте обратиться к
/adminи/user.
Если вы залогинились как admin, то доступ к /admin будет открыт, а /user — закрыт. Для user – всё наоборот.
6. Добавляем несколько ролей к одному методу
Если метод доступен для нескольких ролей, их можно указать как массив:
@Secured({"ROLE_ADMIN", "ROLE_MANAGER"})
public String managerOrAdminMethod() {
return "Привет, Менеджер или Администратор!";
}
Spring Security проверит, принадлежит ли пользователь хотя бы одной из указанных ролей.
Особенности и типичные ошибки
- Роли с префиксом
ROLE_. Spring Security ожидает, что все роли будут начинаться сROLE_. Если вы этого не сделаете, получите ошибку! Например, вместоROLE_ADMINвы указали простоADMIN— это не сработает. - Ошибка
403 Forbidden. Если вы видите эту ошибку, убедитесь, что:- Включена поддержка
@Securedчерез@EnableGlobalMethodSecurity(securedEnabled = true). - Роль пользователя указана правильно (с учётом
ROLE_).
- Включена поддержка
- Не настраивайте роли в контроллерах без обоснования. Безопасность лучше всего ограничивать на уровне сервисов. Это помогает минимизировать дублирование логики.
Практическое применение
Использование ролей и прав доступа — это базовый, но очень мощный инструмент для управления доступом в приложениях. Его используют практически везде: от небольших интернет-магазинов до сложных корпоративных систем. Поэтому понимание работы @Secured — это не просто полезно, это необходимо.
Для более сложных случаев мы будем рассматривать аннотации @PreAuthorize и @PostAuthorize на следующих лекциях — они позволяют настраивать более гибкие правила доступа с использованием SpEL (Spring Expression Language).
ПЕРЕЙДИТЕ В ПОЛНУЮ ВЕРСИЮ