ajax - Ajax GET 请求后表单提交失败(无效的 CSRF 令牌)。怎么修?
问题描述
我有一个提交 POST 请求的“客户详细信息”表单。这是在 Spring Boot 应用程序中,并作为 Thymeleaf 模板实现。我刚刚在表单中添加了一个小 AJAX 功能——当用户单击某个按钮时,它使用jQuery.ajax()根据客户地址查找地理代码。AJAX 调用是一个 GET 请求。
如果我输入客户表单并单击“提交”而不触摸 Ajax 按钮,它会正常提交。但是如果我先使用 Ajax 按钮,然后尝试提交表单,它会被CsrfFilter
一条消息“ Invalid CSRF token found for http://...
”停止。
我假设 Ajax 调用以某种方式使 CSRF 令牌过期,因此需要一个新令牌,但我该如何防止呢?
有一些类似这样的问题,但在这种情况下,他们正在寻找一种将 CSRF 令牌添加到 Ajax 请求的方法。此外,我正在使用 Thymeleaf 视图,因此我将 CSRF 令牌自动插入到我的表单中——我不必手动添加它。
解决方案
问题是我已经实现了一个自定义过滤器来删除每个请求的安全上下文。这是我使应用程序无状态的方式,正如我在这个软件工程 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);
}
}
推荐阅读
- python - 管理员处的 Django TypeError:预期的 str、字节或 os.PathLike 对象,而不是 PosixPath
- javascript - 选择输入打开或关闭时更新输入类型选择的状态
- python - 部署项目时在heroku上出错?
- javascript - 如何在 React 中将数据从 API 添加到日历(不要使用 React-big-calendar)
- html - How to handle ellipsis and multiline flex with align items?
- adobe-indesign - 在 Adobe Indesign 中缩放图像的更快方式/快捷方式
- chart.js - ChartJS 生成日期格式
- javascript - 使用 Chart js 的 PHP 动态图表
- github - 如何使用 Jenkins Jobs 在 GitHub 中关闭拉取请求
- python - 二维数组的近似函数