Карта / JWT и роли / Роли, @PreAuthorize

Роли, @PreAuthorize

Авторизация — «что тебе можно?» После того как мы знаем кто ты (аутентификация), нужно решить, к каким ресурсам у тебя доступ. Самый простой способ — роли: пользователю присваиваются роли (USER, ADMIN, MODERATOR), каждый endpoint требует определённую роль.

Два способа настройки доступа в Spring Security:

1. Через конфигурацию SecurityFilterChain:

http.authorizeHttpRequests(auth -> auth
    .requestMatchers("/admin/**").hasRole("ADMIN")
    .requestMatchers("/api/**").hasAnyRole("USER", "ADMIN")
    .requestMatchers("/public/**").permitAll()
    .anyRequest().authenticated()
);

2. Через @PreAuthorize на методах (более гибко):

@PreAuthorize("hasRole('ADMIN')")
public void deleteUser(Long id) { ... }

@PreAuthorize("hasRole('USER') and #userId == authentication.name")
public UserDto getUser(Long userId) { ... }  // только свой профиль

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

Копнуть глубже

RBAC vs ABAC. Role-Based Access Control (RBAC) — контроль по ролям, просто и понятно. Attribute-Based Access Control (ABAC) — контроль по атрибутам (роль + отдел + время суток + IP). Spring Security поддерживает ABAC через SpEL в @PreAuthorize — любые условия. Для большинства приложений RBAC достаточно.

Роли в JWT. Роли принято класть в payload токена (claim roles или authorities). Spring Security при валидации JWT автоматически извлекает authorities и кладёт в SecurityContext — тогда @PreAuthorize работает без запроса к БД на каждый запрос. Важно: что в токене — то и есть роль, обновление роли в БД вступит в силу только после перевыпуска токена (ещё один аргумент за короткий access token).

@PostAuthorize — проверка после выполнения метода, когда нужно проверить результат:

@PostAuthorize("returnObject.owner == authentication.name")
public Document getDocument(Long id) { ... }  // вернёт документ, только если ты его владелец

Иерархия ролей. Можно настроить, что ADMIN автоматически включает все права USER:

@Bean
RoleHierarchy roleHierarchy() {
    return RoleHierarchyImpl.fromHierarchy("ROLE_ADMIN > ROLE_USER");
}
🎤 Закрыл тему, если можешь объяснить:
• разницу аутентификации и авторизации;
• как настроить доступ по ролям через конфигурацию и @PreAuthorize (если дошёл до 2-го слоя).