JavaRush /Курсы /Модуль 5. Spring /Пользовательские роли и права доступа: аннотация @Secured...

Пользовательские роли и права доступа: аннотация @Secured

Модуль 5. Spring
10 уровень , 4 лекция
Открыта

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

Представьте, что вы разрабатываете банковское приложение: клиент может видеть свои счета, переводить средства, но не может, например, генерировать банковские отчёты. А вот администратор может. Чтобы управлять этим разделением на уровне кода, используется роль-ориентированная система доступа. В 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(); // Шифруем пароли
    }
}
Пароли обязательно должны быть зашифрованы! Используем 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. Тестируем приложение

Запускаем приложение и тестируем:

  1. Откройте Postman или просто браузер.
  2. Попробуйте обратиться к /admin и /user.

Если вы залогинились как admin, то доступ к /admin будет открыт, а /user — закрыт. Для user – всё наоборот.

6. Добавляем несколько ролей к одному методу

Если метод доступен для нескольких ролей, их можно указать как массив:


@Secured({"ROLE_ADMIN", "ROLE_MANAGER"})
public String managerOrAdminMethod() {
    return "Привет, Менеджер или Администратор!";
}

Spring Security проверит, принадлежит ли пользователь хотя бы одной из указанных ролей.


Особенности и типичные ошибки

  1. Роли с префиксом ROLE_. Spring Security ожидает, что все роли будут начинаться с ROLE_. Если вы этого не сделаете, получите ошибку! Например, вместо ROLE_ADMIN вы указали просто ADMIN — это не сработает.
  2. Ошибка 403 Forbidden. Если вы видите эту ошибку, убедитесь, что:
    • Включена поддержка @Secured через @EnableGlobalMethodSecurity(securedEnabled = true).
    • Роль пользователя указана правильно (с учётом ROLE_).
  3. Не настраивайте роли в контроллерах без обоснования. Безопасность лучше всего ограничивать на уровне сервисов. Это помогает минимизировать дублирование логики.

Практическое применение

Использование ролей и прав доступа — это базовый, но очень мощный инструмент для управления доступом в приложениях. Его используют практически везде: от небольших интернет-магазинов до сложных корпоративных систем. Поэтому понимание работы @Secured — это не просто полезно, это необходимо.

Для более сложных случаев мы будем рассматривать аннотации @PreAuthorize и @PostAuthorize на следующих лекциях — они позволяют настраивать более гибкие правила доступа с использованием SpEL (Spring Expression Language).

Комментарии
ЧТОБЫ ПОСМОТРЕТЬ ВСЕ КОММЕНТАРИИ ИЛИ ОСТАВИТЬ КОММЕНТАРИЙ,
ПЕРЕЙДИТЕ В ПОЛНУЮ ВЕРСИЮ