JavaRush /Курсы /Модуль 5. Spring /Конфигурация безопасности через аннотации

Конфигурация безопасности через аннотации

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

Spring Security предоставляет мощный механизм для конфигурации безопасности через аннотации. Это делает наш код не только компактнее, но и более читаемым. Аннотации позволяют разграничивать доступ к ресурсам и методам прямо там, где они используются.

В этой лекции мы изучим четыре основные аннотации:

  • @Secured
  • @RolesAllowed
  • @PreAuthorize
  • @PostAuthorize

Аннотация @Secured

Аннотация @Secured задаёт роли, которым разрешён доступ к методу или ресурсу. Она является простой и удобной, если вам нужен быстрый способ ограничить доступ на основе ролей.

@Secured проверяет, есть ли у пользователя определённая роль (например, ROLE_USER), чтобы он мог вызвать данный метод.

Пример:


import org.springframework.security.access.annotation.Secured;
import org.springframework.stereotype.Service;

@Service
public class MyService {

    @Secured("ROLE_ADMIN")
    public void adminOnlyMethod() {
        System.out.println("Этот метод доступен только для администраторов!");
    }

    @Secured({"ROLE_USER", "ROLE_ADMIN"})
    public void userOrAdminMethod() {
        System.out.println("Этот метод доступен для пользователей и администраторов.");
    }
}
Простая проверка ролей — ничто, по сравнению с отсутствием этого метода. Но не забывайте: чтобы аннотация заработала, нужно в конфигурации активировать @EnableGlobalMethodSecurity с параметром securedEnabled = true.

Как активировать? Добавьте следующую настройку в класс конфигурации безопасности:


import org.springframework.context.annotation.Configuration;
import org.springframework.security.config.annotation.method.configuration.EnableGlobalMethodSecurity;

@Configuration
@EnableGlobalMethodSecurity(securedEnabled = true) // Включаем поддержку @Secured
public class SecurityConfig {
    // Здесь можно добавлять дополнительные конфигурации
}

Аннотация @RolesAllowed

@RolesAllowed — это аннотация из стандарта JSR-250, которая очень похожа на @Secured. Она также проверяет роли пользователя, но является более "официальной" в контексте стандартов Java.

Пример использования:


import javax.annotation.security.RolesAllowed;
import org.springframework.stereotype.Service;

@Service
public class AnotherService {

    @RolesAllowed("ROLE_MANAGER")
    public String managerOnly() {
        return "Доступно только для менеджеров!";
    }
}

Включение @RolesAllowed. Чтобы эта аннотация работала, нужно активировать её в конфигурации безопасности:


import org.springframework.context.annotation.Configuration;
import org.springframework.security.config.annotation.method.configuration.EnableGlobalMethodSecurity;

@Configuration
@EnableGlobalMethodSecurity(jsr250Enabled = true) // Включаем поддержку @RolesAllowed
public class SecurityConfig {
}
Помните: если вы используете @Secured и @RolesAllowed одновременно, то активировать нужно оба параметра ( securedEnabled = true и jsr250Enabled = true).

Аннотация @PreAuthorize

Это уже более мощная аннотация, которая позволяет использовать SpEL (Spring Expression Language) для определения условий доступа. Можно проверять не только роли, но и значения атрибутов объекта, который метод получает на вход.

Например, вы можете написать условие вроде "доступ разрешён только пользователям, у которых email заканчивается на @example.com".

Пример:


import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.stereotype.Service;

@Service
public class EmailService {

    @PreAuthorize("hasRole('ROLE_USER')")
    public void generalAccess() {
        System.out.println("Этот метод доступен только для пользователей с ролью ROLE_USER.");
    }

    @PreAuthorize("#email.endsWith('@example.com')")
    public void sendEmail(String email) {
        System.out.println("Отправка email на адрес: " + email);
    }
}
В первом методе проверяются роли через hasRole, а во втором используется выражение, зависящее от параметра метода.

Включение @PreAuthorize

Чтобы активировать поддержку этой аннотации, добавьте в конфигурацию:


import org.springframework.context.annotation.Configuration;
import org.springframework.security.config.annotation.method.configuration.EnableGlobalMethodSecurity;

@Configuration
@EnableGlobalMethodSecurity(prePostEnabled = true) // Включаем поддержку @PreAuthorize и @PostAuthorize
public class SecurityConfig {
}

Аннотация @PostAuthorize

Чем она отличается от @PreAuthorize? Если @PreAuthorize проверяет доступ до вызова метода, то @PostAuthorize делает это после выполнения метода. Это может быть полезно, когда вы хотите проверить результат выполнения метода перед тем, как вернуть его вызвавшей стороне.

Пример:


import org.springframework.security.access.prepost.PostAuthorize;
import org.springframework.stereotype.Service;

@Service
public class DocumentService {

    @PostAuthorize("returnObject.owner == authentication.name")
    public Document getDocumentById(Long id) {
        Document document = findDocumentById(id); // Логика поиска документа
        return document; // Проверка, что текущий пользователь является владельцем документа
    }
}

В этом примере разрешение возвращать документ проверяется уже после того, как метод его нашёл. Если текущий пользователь не является владельцем документа, Spring Security выбросит исключение.


Role-based Access Control (RBAC)

Теперь, когда мы изучили аннотации, давайте обсудим, как это всё связано с концепцией управления доступом на основе ролей.

В системе RBAC пользователи получают определённые роли (например, ROLE_USER, ROLE_ADMIN), а уже роли имеют доступ к определённым ресурсам. Это позволяет эффективно управлять правами доступа, централизованно задавая правила.


Практика: Настройка безопасности с аннотациями

Давайте создадим сервис, где пользователи могут:

  1. Посмотреть список своих задач (доступно только пользователям с ролью ROLE_USER).
  2. Удалить задачу (доступно только администраторам).

public class Task {

    private Long id;
    private String name;
    private String owner;

    // Getters и Setters
}

Сервис:


import org.springframework.security.access.annotation.Secured;
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.stereotype.Service;

import java.util.ArrayList;
import java.util.List;

@Service
public class TaskService {

    private List<Task> tasks = new ArrayList<>();

    public TaskService() {
        // Добавим несколько задач для примера
        tasks.add(new Task(1L, "Купить молоко", "user1"));
        tasks.add(new Task(2L, "Сделать домашку", "user2"));
    }

    @PreAuthorize("hasRole('ROLE_USER')")
    public List<Task> getUserTasks(String owner) {
        // Логика фильтрации задач по владельцу
        return tasks.stream()
                    .filter(task -> task.getOwner().equals(owner))
                    .toList();
    }

    @Secured("ROLE_ADMIN")
    public void deleteTask(Long id) {
        // Логика удаления задачи
        tasks.removeIf(task -> task.getId().equals(id));
    }
}

Контроллер:


import org.springframework.web.bind.annotation.*;

import java.util.List;

@RestController
@RequestMapping("/tasks")
public class TaskController {

    private final TaskService taskService;

    public TaskController(TaskService taskService) {
        this.taskService = taskService;
    }

    @GetMapping
    public List<Task> getTasks(@RequestParam String owner) {
        return taskService.getUserTasks(owner);
    }

    @DeleteMapping("/{id}")
    public void deleteTask(@PathVariable Long id) {
        taskService.deleteTask(id);
    }
}

Теперь мы настроили авторизацию как через роли, так и через выражения.


Типичные ошибки

  1. Забыли активировать аннотации: если не включить @EnableGlobalMethodSecurity, никакая аннотация работать не будет.
  2. Отсутствие ролей у пользователя: если у пользователя не назначены роли, все защищённые методы будут для него недоступны.
  3. Смешивание разных аннотаций: если вы используете и @PreAuthorize, и @Secured, не забывайте включить поддержку обоих параметров.

Теперь вы знаете, как конфигурировать безопасность с помощью аннотаций. Это мощный инструмент, который упрощает управление доступом в приложениях.

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