Ответ
CSRF-токен (Cross-Site Request Forgery token) — это уникальный криптографический токен, который сервер генерирует для сессии пользователя и требует его наличие во всех state-changing запросах для защиты от CSRF-атак.
Как работает защита:
- Сервер генерирует токен и привязывает его к сессии пользователя
- Токен встраивается в HTML-формы как скрытое поле или добавляется в заголовки
- При получении POST/PUT/DELETE запроса сервер сравнивает токен из запроса с токеном в сессии
- Запрос без валидного токена отклоняется
Пример реализации в Spring Security:
@Configuration
@EnableWebSecurity
public class SecurityConfig {
@Bean
public SecurityFilterChain filterChain(HttpSecurity http) throws Exception {
http
.csrf(csrf -> csrf
.csrfTokenRepository(CookieCsrfTokenRepository.withHttpOnlyFalse())
// Исключение API endpoints, если нужно
.ignoringRequestMatchers("/api/public/**")
);
return http.build();
}
}
В Thymeleaf форме токен добавляется автоматически:
<form method="post" action="/transfer">
<!-- Thymeleaf автоматически добавит скрытое поле с токеном -->
<input type="hidden" name="amount" value="1000">
<input type="hidden" name="toAccount" value="12345">
<button type="submit">Перевести деньги</button>
</form>
<!-- Сгенерирует: <input type="hidden" name="_csrf" value="a1b2c3d4..."> -->
Для AJAX-запросов:
// Получаем токен из cookie или meta-тега
const csrfToken = document.querySelector('meta[name="_csrf"]').content;
const csrfHeader = document.querySelector('meta[name="_csrf_header"]').content;
// Добавляем в заголовок
fetch('/api/update', {
method: 'POST',
headers: {
'Content-Type': 'application/json',
[csrfHeader]: csrfToken // Например: 'X-CSRF-TOKEN': 'a1b2c3d4'
},
body: JSON.stringify(data)
});
Важные особенности:
- Токен должен быть непредсказуемым и уникальным для сессии
- Используется только для защиты аутентифицированных запросов
- Не защищает от XSS — если злоумышленник может выполнить JavaScript, он может украсть токен
- SameSite cookie attribute — дополнительная защита на уровне браузера