jQuery Ajax调用Spring POST接口异常 返回完整HTML页面问题
问题根因
该现象是Spring Security默认开启CSRF跨站请求伪造防护导致的:
CSRF防护默认会放行GET、HEAD、OPTIONS这类幂等请求,仅对POST、PUT、DELETE等非幂等请求做Token校验。你的POST请求没有携带合法CSRF Token时,请求会被Spring Security拦截,直接重定向到错误页/登录页,最终返回对应页面的HTML代码,根本没有进入你写的Controller方法逻辑;而GET请求因为被CSRF过滤器放行,所以能正常进入接口返回预期结果。
你可以先在浏览器开发者工具的网络面板核对两个特征确认:
- POST请求的首个响应状态码为
302,后续自动跳转后的请求才返回200状态和HTML内容 - 返回的HTML内容为系统登录页或者403错误提示页
修复方案
根据项目实际场景二选一即可:
方案1:请求携带CSRF Token(生产环境同域部署推荐)
如果是前后端不分离的同域项目,不需要关闭CSRF,只需要让Ajax请求自动携带服务端生成的CSRF Token即可。
- 先在页面头中存入服务端渲染时注入的CSRF参数(使用Thymeleaf等模板引擎时会自动生成,手动编写参考如下):
<meta name="_csrf" content="${_csrf.token}" /> <meta name="_csrf_header" content="${_csrf.headerName}" />
- 全局配置jQuery Ajax,所有请求自动携带CSRF请求头:
$(function() { const csrfToken = $("meta[name='_csrf']").attr("content"); const csrfHeader = $("meta[name='_csrf_header']").attr("content"); $(document).ajaxSend(function(e, xhr) { xhr.setRequestHeader(csrfHeader, csrfToken); }); });
配置完成后原有业务代码不需要修改,POST请求即可正常返回接口内容。
方案2:关闭CSRF防护(纯前后端分离/接口服务场景使用)
如果你的项目是纯前后端分离架构,使用JWT、token等其他认证机制,不需要CSRF防护,可以直接在Spring Security配置类中关闭CSRF校验:
@Configuration @EnableWebSecurity public class WebSecurityConfig extends WebSecurityConfigurerAdapter { @Override protected void configure(HttpSecurity http) throws Exception { http .csrf().disable() // 关闭CSRF校验 // 下方保留你项目原有权限、登录相关配置即可 .authorizeRequests() .anyRequest().permitAll(); } }
重启服务后POST请求即可正常命中Controller接口。
补充排查点
如果上述配置完成后问题仍存在,可核对两点:
- 确认Controller类上是否添加了
@RestController注解或类级别的@ResponseBody注解,你当前GET请求可正常返回,该配置大概率无问题 - 排查项目中自定义的拦截器、过滤器是否优先拦截了POST路径,可在拦截逻辑中打印日志确认请求是否被提前拦截
内容的提问来源于stack exchange,提问作者Cipher
相关产品推荐
相关产品推荐

