添加ActiveDirectory认证后Spring Boot @RestController POST请求报403错误
问题原因及解决方案
核心原因
Spring Security默认启用CSRF(跨站请求伪造)防护机制,对非GET类型的请求(如POST)会强制校验CSRF令牌:
- 标准HTML表单提交时,Spring会自动生成隐藏的CSRF输入字段,提交时自动携带令牌,因此能通过校验
- Ajax请求不会自动携带CSRF令牌,所以被Spring Security拦截,返回403错误
- GET请求本身不触发CSRF校验(因为GET不应修改服务器状态),所以能正常工作
解决方案
1. 前端Ajax补充CSRF令牌请求头
方式1:通过页面Meta标签获取令牌
首先在页面的<head>中添加CSRF令牌的Meta标签(后端会自动注入令牌值,若用Thymeleaf等模板引擎可直接使用):
<meta name="_csrf" content="${_csrf.token}"> <meta name="_csrf_header" content="${_csrf.headerName}">
修改Ajax代码,添加令牌头:
// 获取CSRF令牌及对应的请求头名称 var csrfToken = $("meta[name='_csrf']").attr("content"); var csrfHeader = $("meta[name='_csrf_header']").attr("content"); $.ajax({ async: false, type: "POST", url: "/rest/api/1/command", contentType: "application/json", dataType: "json", // 注意:contentType为json时,需将data转为JSON字符串,否则jQuery会默认用form-data格式发送 data: JSON.stringify({ command: "run" }), // 发送请求前设置CSRF头 beforeSend: function(xhr) { xhr.setRequestHeader(csrfHeader, csrfToken); }, success: function (data) { return true; } });
方式2:从Cookie中读取令牌
如果后端配置了将CSRF令牌存储在Cookie中,可直接从Cookie读取:
// 原生JS读取Cookie的工具函数 function getCookie(name) { var value = "; " + document.cookie; var parts = value.split("; " + name + "="); if (parts.length === 2) return parts.pop().split(";").shift(); } var csrfToken = getCookie('XSRF-TOKEN'); $.ajax({ async: false, type: "POST", url: "/rest/api/1/command", contentType: "application/json", dataType: "json", data: JSON.stringify({ command: "run" }), // 设置CSRF请求头 headers: { 'X-XSRF-TOKEN': csrfToken }, success: function (data) { return true; } });
2. 后端Spring Security配置补充
在你的ActiveDirectoryConfig类中,重写configure(HttpSecurity http)方法,确保CSRF配置正确(推荐保留CSRF防护,不要关闭):
@Override protected void configure(HttpSecurity http) throws Exception { http // 配置所有请求需要认证 .authorizeRequests() .anyRequest().authenticated() .and() // 配置登录方式(根据你的实际认证场景调整,比如表单登录或Basic Auth) .formLogin() .permitAll() .and() // 配置CSRF令牌存储方式,允许前端访问Cookie中的令牌 .csrf() .csrfTokenRepository(CookieCsrfTokenRepository.withHttpOnlyFalse()); }
额外注意点
原Ajax代码中data: { command: "run" }存在格式问题:当contentType设为application/json时,需要将JS对象转为JSON字符串(用JSON.stringify()),否则jQuery会默认以application/x-www-form-urlencoded格式发送数据,导致后端@RequestBody无法解析请求体。
内容的提问来源于stack exchange,提问作者nn4l
相关产品推荐
相关产品推荐

