tgoop.com/BookJava/3832
Last Update:
В асинхронных или веб-сервисах на реактиве нужно быть осторожным: SecurityContext не “переходит” автоматически в новые потоки. Для этого используют SecurityContextRepository и специальные методы в WebFlux.
⚠️ Важно: не храните SecurityContext в сессии, если у вас stateless-приложение (REST API). Вместо сессии используйте JWT или OAuth 2.0.
🧠 5. Авторизация: FilterSecurityInterceptor & AccessDecisionManagerFilterSecurityInterceptor запускается в конце цепочки фильтров и проверяет доступ к URL. Он запрашивает у SecurityMetadataSource список необходимых ролей для данного эндпоинта (Spring на основании @PreAuthorize, HttpSecurity конфигурации или XML). Затем передаёт дело в AccessDecisionManager (по умолчанию AffirmativeBased), который опрашивает список AccessDecisionVoter (например, RoleVoter для проверок ролей, WebExpressionVoter для SpEL).
FilterSecurityInterceptor
└─> SecurityMetadataSource (что нужно: ROLE_ADMIN)
└─> AccessDecisionManager.vote()
├─ RoleVoter.vote() → совпадает?
└─ WebExpressionVoter.vote() → SpEL-выражения?
Если хотя бы один голос “grant”,
AffirmativeBased отпускает запрос (по умолчанию). Можно менять стратегию на Consensus или Unanimous.💡 Трюк: чтобы локально протестировать SecurityContext, можно в тестах использовать аннотацию
@WithMockUser(roles = "ADMIN") и проверять, что нужный эндпоинт доступен.🧠 6. Аннотации & Method Security
Помимо URL-уровня, есть методная проверка:
@EnableMethodSecurity // (Spring Boot 3+) вместо @EnableGlobalMethodSecurity
public class SecurityConfig { ... }
// Где-то в сервисе:
@PreAuthorize("hasRole('ADMIN') and #id == principal.id")
public void deleteUser(Long id) { ... }
* 📌
@PreAuthorize / @PostAuthorize / @Secured / @RolesAllowed — все используют тот же механизм Voter’ов, но проверяют уже на методах сервиса.* 💡 Совет: включайте методную безопасность только там, где действительно нужна тонкая грануляция.
🧠 7. Хранение паролей & PasswordEncoder
С Java 17+ используйте
PasswordEncoder с алгоритмами Argon2 или BCrypt:
@Bean
public PasswordEncoder passwordEncoder() {
return new BCryptPasswordEncoder(12);
}
⚠️ Никогда не храните пароли в открытом виде и не используйте MD5/SHA-1 — они считаются небезопасными.
🧠 8. Stateless vs Stateful
* Stateful (Сессии): Spring создаёт HTTP-сессию, а
SecurityContextPersistenceFilter хранит контекст в сессии. Удобно для монолитов с классическим web-приложением.* Stateless (JWT/OAuth2): убираем
SessionCreationPolicy.STATELESS, используем BearerTokenAuthenticationFilter, аутентификация и авторизация проверяются по JWT в каждом запросе.💡 Современный стек (Spring Boot 3+):
1. Настраиваем
SecurityFilterChain с oauth2ResourceServer().jwt().2. Подключаем
spring-boot-starter-oauth2-resource-server.3. Указываем
issuer-uri или jwk-set-uri в application.yml.
spring:
security:
oauth2:
resourceserver:
jwt:
issuer-uri: https://keycloak.example.com/realms/myrealm
🧠 9. Подпись запросов & CSRF
* По умолчанию CSRF включён для “форменных” запросов (
POST, PUT, DELETE). Для stateless-API его обычно отключают:
http.csrf().disable();
* Если используете формы, не забудьте добавить в шаблон:
<input type="hidden" name="${_csrf.parameterName}" value="${_csrf.token}"/>
⚠️ Внимание: не отключайте CSRF, если ваше приложение использует сессии и cookie на фронтенде!
💡 Совет по отладке: включите логирование фильтров:
logging.level.org.springframework.security=DEBUG
Тогда в логах вы увидите, как проходит запрос через каждый фильтр и где происходит отказ.
👉@BookJava
BY Библиотека Java разработчика
Share with your friend now:
tgoop.com/BookJava/3832
