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

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

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

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

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

Ответ 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");
    }
}

Ответ 2

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

Ответ 3

Вы также можете сделать вашу защиту CSRF опираться на куки файлы и состояние сеанса на стороне сервера. Spring Безопасность имеет полную поддержку для этого.

CookieCsrfTokenRepository

Вы получите только время ожидания, если ваш файл cookie истечет. Это хорошо масштабируется, так как оно в основном безгосударственно (с точки зрения сервера).

@EnableWebSecurity
public class WebSecurityConfig extends
        WebSecurityConfigurerAdapter {

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

Эндрю