Ошибка отправки формы (неверный токен CSRF) после запроса Ajax GET. Как исправить? - PullRequest
0 голосов
/ 06 апреля 2020

У меня есть форма "Сведения о клиенте", которая отправляет запрос POST. Это в приложении Spring Boot и реализовано в виде шаблона Thymeleaf. Я только что добавил небольшую функцию AJAX к форме - когда пользователь нажимает определенную кнопку, он использует jQuery. ajax () , чтобы найти геокод на основе адрес клиента. Вызов AJAX является запросом GET.

Если я введу форму клиента и нажму «Отправить», не нажимая кнопку Ajax, он отправляется в обычном режиме. Но если я сначала использую кнопку Ajax, а затем пытаюсь отправить форму, она CsrfFilter останавливается с сообщением "Invalid CSRF token found for http://...".

Я предполагаю, что Ajax вызов как-то приводит к истечению срока действия токена CSRF, так что нужен новый, но как я могу предотвратить это?

Есть несколько похожих вопросов, таких как этот но в этом случае они ищут способ добавить токен CSRF в Ajax запрос. Кроме того, я использую представления Thymeleaf, поэтому я автоматически вставляю токен CSRF в мою форму - мне не нужно добавлять его вручную.

1 Ответ

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

Проблема заключалась в том, что я реализовал пользовательский фильтр для удаления контекста безопасности при каждом запросе. Это был мой способ сделать приложение без состояний , как я задокументировал в этом ответе SE на разработку программного обеспечения . Это удаляет (или сбрасывает?) Токен CSRF на стороне сервера, чтобы он не совпадал с маркером в форме, однако пользовательский фильтр запускает после CsrfFilter, поэтому у меня никогда не возникало проблем с формой перед отправкой.

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

Я исправил это, изменив пользовательский фильтр, чтобы пропустить удаление контекста, если URL находится под определенным путем к каталогу:

public class SecurityContextDeletingFilter extends GenericFilterBean {

    RequestMatcher exceptedPaths = new AntPathRequestMatcher("/form-ajax/**");

    @Override
    public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
        final HttpServletRequest request = (HttpServletRequest) servletRequest;
        final HttpSession session = request.getSession();

        if( exceptedPaths.matches(request)) {
            // Deleting the security context deletes the CSRF token in the session. We want to make sure this
            // does NOT occur if the user is in a form and is using Ajax features like the geocode lookup,
            // because they'll need the server to recognize the token on eventual form submission.
            logger.trace("Skipping this filter for a /form-ajax/ endpoint.");
        } else {
            if( session.getAttribute(HttpSessionSecurityContextRepository.SPRING_SECURITY_CONTEXT_KEY) != null ) {
                session.removeAttribute(HttpSessionSecurityContextRepository.SPRING_SECURITY_CONTEXT_KEY);
            }
        }

        filterChain.doFilter(servletRequest,servletResponse);
    }
}
...