Ответ 1
Рекомендуемое решение
Я бы сказал, что вы не должны отключать токены csrf на производственном сайте. Вы можете заставить сеанс (и, следовательно, токен csrf) длиться дольше (но обычно он не должен длиться дольше, чем день, особенно для не вошедших в систему пользователей, поскольку это вектор DOS), но реальным решением может быть автоматическое обновление страница входа в систему по истечении срока действия токена csrf. Вы можете использовать
<META HTTP-EQUIV="REFRESH" CONTENT="csrf_timeout_in_seconds">
в заголовке страницы входа. Если пользователь позволяет странице входа сидеть часами, его не должно беспокоить, что страница обновилась.
Второе решение
Возможное решение, которое не требует от вас фактического хранения сеансов, но допускает бесконечное время ожидания, состоит в том, что вы можете сгенерировать свои токены csrf с хэшированием из идентификатора сеанса и секрета на стороне сервера:
csrf = hash(sessionid+secret)
Однако обратите внимание, что вам нужно по-настоящему копать и переопределять внутренние механизмы Spring-Security, а именно:
- повторное создание анонимных сессий на лету, если поступает запрос, и такой сессии не существует
- воссоздание токена csrf на лету из идентификатора сеанса
И выберите очень безопасный алгоритм хеширования, предпочтительно sha-512.
Третье решение
У вас может быть небольшой javascript, который регулярно вызывает неактивную страницу на вашем сервере (незадолго до истечения времени ожидания сеанса), что продлевает ваш сеанс. Это приводит к бесконечному тайм-ауту сеанса, только если браузер все время включен, поэтому аспект DOS смягчается.
Хорошо, последнее решение
Вы можете изменить код проверки токена CSRF и отключить его для страницы входа. На самом деле это синоним второго решения, но оно характерно для страницы входа, а не для всех анонимных сеансов.
Вы можете сделать это, например, установив пользовательский RequestMatcher в HttpSecurity:
http.csrf().requireCsrfProtectionMatcher(new MyCsrfRequestMatcher());
...
class MyCsrfRequestMatcher implements RequestMatcher {
@Override
public boolean matches(HttpServletRequest request) {
return !request.getServletPath().equals("/login");
}
}