Проблема заключалась в том, что я реализовал пользовательский фильтр для удаления контекста безопасности при каждом запросе. Это был мой способ сделать приложение без состояний , как я задокументировал в этом ответе 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);
}
}