Токен CSRF истекает во время входа в систему

Я работаю над весенним веб-приложением, и мне нужно избежать проблемы с истекающим токеном csrf на странице входа в систему, потому что, если пользователь слишком долго ждет и пытается войти в систему, только один способ решить проблему с csrf-перезагрузить страницу и попытаться войти снова. Но это не удобно для пользователя, и я хочу избежать этой ситуации.

первый вопрос: возможно ли вообще (по spring security 3.2.4)? Без отключения csrf.

Я попытался использовать security= "none" для страницы входа и весны seciruty "login_check", но он не работает, у меня есть перенаправление бесконечности или я получил ошибку, что нет сопоставления для url"myhost/login_check".

второй вопрос: Как я могу это сделать?

3 ответов


рекомендуемое решение

Я бы сказал, что вы не должны отключать токены csrf на производственном сайте. Вы можете сделать сеанс (и, следовательно, токен csrf) дольше (но он обычно не должен длиться дольше дня, особенно для не вошедших в систему пользователей, поскольку это вектор DOS), но реальным решением может быть автоматическое обновление страницы входа в систему, когда токен csrf истекает. Вы можете использовать

<META HTTP-EQUIV="REFRESH" CONTENT="csrf_timeout_in_seconds">

в заголовке страницы входа. Если пользователь позволяет странице входа сидеть для часы, его не должно беспокоить, что страница обновилась.

второй вариант

возможное решение, которое не требует от вас фактического хранения сеансов, но допускает бесконечное время ожидания, заключается в том, что вы можете генерировать свои токены csrf с хэшированием из идентификатора сеанса и серверного секрета:

csrf = hash(sessionid+secret)

обратите внимание, однако, что вам нужно действительно копать и переопределять внутренние механизмы spring-security, а именно:

  • повторное создание anonymous сеансы "на лету", если поступает запрос и такой сессии не существует
  • повторное создание токена csrf на лету из идентификатора сеанса

и выберите очень безопасный алгоритм хэширования, предпочтительно sha-512.

Третий способ

у вас может быть небольшой javascript, который вызывает страницу no-op на вашем сервере регулярно (непосредственно перед таймаутом сеанса), таким образом, продлевая сеанс. Это приводит к бесконечному таймауту сеанса, только если браузер включен все время, поэтому аспект DOS смягчается.

Ok, последнее решение

вы можете изменить код проверки маркера CSRF и отключить его для страницы входа в систему. Это фактически синоним второго решения, но специфично для страницы входа в систему, а не для всех анонимных сеансов.

вы можете сделать это, например, установив пользовательский RequestMatcher в HttpSecurity:

http.csrf().requireCsrfProtectionMatcher(new MyCsrfRequestMatcher());
...
class MyCsrfRequestMatcher implements RequestMatcher {
    @Override
    public boolean matches(HttpServletRequest request) {
        return !request.getServletPath().equals("/login");
    }
}

другой вариант не будет установлен тайм-аут для сеанса по умолчанию, а затем, когда пользователь аутентифицируется, измените тайм-аут на то, что вы хотите. Вы можете увидеть пример того, как это сделать здесь.


вы также можете сделать свою защиту CSRF полагаться на cookies, а не на состояние сеанса на стороне сервера. Spring Security полностью поддерживает это.

CookieCsrfTokenRepository

вы получите тайм-аут, Если ваш cookie истекает. Это хорошо масштабируется, так как это в основном без состояния (с точки зрения сервера).

@EnableWebSecurity
public class WebSecurityConfig extends
        WebSecurityConfigurerAdapter {

    @Override
    protected void configure(HttpSecurity http) throws Exception {
        http
            .csrf()
                .csrfTokenRepository(CookieCsrfTokenRepository.withHttpOnlyFalse());
    }
}

Андрей