Заказы фильтра CSRF и генерация случайных токенов - PullRequest
0 голосов
/ 24 апреля 2020

Я испытываю странное поведение в отношении генерации токенов XSRF и обновляю необходимые значения cook ie. Когда я загружаю целевую страницу моего сайта - Angular front-end и Spring-boot back-end - генерируется маркер XSRF. Нет, идеально, но если это нормально и ожидаемо, тогда я в порядке. Единственными запросами, которые генерируются при переходе на целевую страницу, являются запросы «GET».

После того, как я войду в приложение, оно проверяет первый XSRF-TOKEN, проверяет его действительность и переходит к входу в систему. Однако новый токен CSRF генерируется сразу после изменения XSRF-TOKEN в веб-сервисе. Er go, интерфейс и бэкэнд теперь не синхронизированы c. Я не уверен, как либо обновить XSRF-TOKEN после успешного входа в систему, либо не допустить его изменения, поскольку, похоже, в этом нет никакой пользы ... по крайней мере, из того, что я прочитал.

Web Security

@Override
protected void configure(HttpSecurity http) throws Exception {
    CsrfHeaderFilter csrfHeaderFilter = new CsrfHeaderFilter();

    http.httpBasic()
        .authenticationEntryPoint(new AuthenticationFailureHandler())
        .and()
            .authorizeRequests()
            .antMatchers("List of API URI").permitAll()
            .anyRequest().authenticated();

    // Configurations for CSRF end points
    http.httpBasic()
        .authenticationEntryPoint(new AuthenticationFailureHandler())
        .and()
            .csrf()
            .csrfTokenRepository(CookieCsrfTokenRepository.withHttpOnlyFalse())
        .and()
            .authorizeRequests()
            .antMatchers("Login API URI").permitAll()
        .and()
            .addFilterAfter(csrfHeaderFilter, CsrfFilter.class);

        // Logout configurations
        http.logout()
        .permitAll()
        .logoutSuccessHandler((new HttpStatusReturningLogoutSuccessHandler(HttpStatus.OK)));
}

Раздел csrf был разделен в надежде, что токены csrf будут сгенерированы только в том случае, если с этим URI был отправлен запрос на отправку. Кажется, это не так. Похоже, что фильтр заголовка CSRF вызывается независимо от того, какой URI отправляется бэкэнду.

Фильтр заголовка CSRF - требуется, поскольку домен cook ie должен быть обновлен, чтобы разрешить переднему и бэкэнду иметь доступ к XSRF-TOKEN.

@Override
protected void doFilterInternal(HttpServletRequest request,
                                  HttpServletResponse response, FilterChain filterChain)
          throws ServletException, IOException {

    CsrfToken csrf = (CsrfToken) request.getAttribute(CsrfToken.class
            .getName());

    if (csrf != null) {
      Cookie cookie = WebUtils.getCookie(request, "XSRF-TOKEN");
      String token = csrf.getToken();
      if (cookie == null || (token != null && !token.equals(cookie.getValue()))) {
        cookie = new Cookie("XSRF-TOKEN", token);
        cookie.setPath("/");
        cookie.setDomain(<omitted>);
        response.addCookie(cookie);
      }
    }
    filterChain.doFilter(request, response);
  }

Я полагаю, что существует проблема с организацией моих фильтров, но я попробовал все, начиная с объединения различных разделов http.httpBasi c () в одну группу для использования antIgnores для csrf (), чтобы не обрабатывать токены CSRF с GET-запросами. Будем весьма благодарны за любые рекомендации или предложения!

Если вам понадобится что-нибудь еще, дайте мне знать, и я постараюсь предоставить его.

Спасибо!

1 Ответ

0 голосов
/ 29 апреля 2020

Как я и подозревал, была проблема с порядком фильтрации. Существует иерархия фильтров, которая устанавливается в Spring-Boot Security. XSRF-TOKEN необходимо было сгенерировать до добавления значения для повара ie. Если старое значение добавляется в Cook ie до того, как будет сгенерировано новое значение, то внешний и внутренний интерфейсы будут не синхронизированы c до тех пор, пока не будет выполнено обновление браузера sh.

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

@Override
protected void configure(HttpSecurity http) throws Exception {
CsrfHeaderFilter csrfHeaderFilter = new CsrfHeaderFilter();

http.httpBasic()
    .authenticationEntryPoint(new AuthenticationFailureHandler())
    .and()
        .authorizeRequests()
        .antMatchers("List of API URI").permitAll()
        .anyRequest().authenticated();

// Configurations for CSRF end points
http.httpBasic()
    .authenticationEntryPoint(new AuthenticationFailureHandler())
    .and()
        .csrf()
        .csrfTokenRepository(CookieCsrfTokenRepository.withHttpOnlyFalse())
    .and()
        .authorizeRequests()
        .antMatchers("Login API URI").permitAll()
    .and()
        .addFilterAfter(csrfHeaderFilter, ExceptionTranslationFilter.class);

    // Logout configurations
    http.logout()
    .permitAll()
    .logoutSuccessHandler((new HttpStatusReturningLogoutSuccessHandler(HttpStatus.OK)));
}
...