Роли, @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-го слоя).