
在 Spring Boot 3 + Spring Security 6+ 的测试中,无需修改生产安全配置即可解决 CSRF 导致的 403/406 等测试失败问题:推荐使用 SecurityMockMvcRequestPostProcessors.csrf() 在单个请求中显式添加合法 CSRF Token,而非全局关闭 CSRF 防护。
在 spring boot 3 + spring security 6+ 的测试中,无需修改生产安全配置即可解决 csrf 导致的 403/406 等测试失败问题:推荐使用 `securitymockmvcrequestpostprocessors.csrf()` 在单个请求中显式添加合法 csrf token,而非全局关闭 csrf 防护。
在 Spring Boot 3.x(对应 Spring Security 6.2+)中,CSRF 保护默认启用,且对非幂等请求(如 POST、PUT、DELETE)强制校验。虽然你的生产环境安全配置(如 OAuth2 资源服务器)本身不依赖 Cookie/Session,但 MockMvc 测试默认仍会触发 CsrfFilter 拦截——尤其当测试使用 @WithMockUser 或表单类请求时,若未提供有效 CSRF Token,将直接返回 403 Forbidden 或因内容协商失败出现 406 Not Acceptable(如示例中所示)。
✅ 正确做法:保留生产配置完整性,仅在测试请求中注入模拟 CSRF Token
Spring Security 提供了开箱即用的测试支持工具类 SecurityMockMvcRequestPostProcessors,其中的 csrf() 方法会自动生成并注入一个有效的、与当前 MockMvc Session 绑定的 CSRF Token,完全模拟真实浏览器提交行为:
import static org.springframework.security.test.web.servlet.request.SecurityMockMvcRequestPostProcessors.csrf;
import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.get;
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status;
@Test
@WithMockUser(authorities = "user=admin")
void asAdmin_canGetPhoto() throws Exception {
mockMvc.perform(
get("/photo")
.with(csrf()) // ✅ 关键:显式添加 CSRF 支持
).andExpect(status().isOk());
}
⚠️ 注意事项:
-
csrf()仅适用于基于MockMvc的集成测试,不适用于@WebMvcTest切片测试以外的场景(如@SpringBootTest全量启动需额外确保MockMvcBean 正确配置); - 若测试涉及
POST/PUT等状态变更请求,除.with(csrf())外,还需确保请求体格式正确(如contentType(MediaType.APPLICATION_JSON)),避免因内容协商失败误判为 CSRF 问题; -
切勿在测试配置中全局
.csrf(csrf -> csrf.disable()):这会掩盖真实安全行为,违背“测试即生产”的原则,且可能导致 CI 环境误配风险; - 对于纯 REST API 场景(如 OAuth2 Resource Server),生产配置本就不应依赖 Cookie,因此 CSRF 实际无效;但测试仍需
csrf()模拟,因为MockMvc默认启用所有过滤器链。
? 补充:若需为全部测试统一启用 CSRF 支持(不推荐,降低可读性),可通过自定义 MockMvcBuilder 实现,但强烈建议坚持“按需显式添加”原则——它清晰表达了每个测试对安全上下文的预期,提升可维护性与安全性意识。
总之,在 Spring Boot 3 的现代化测试实践中,with(csrf()) 是精准、安全、符合框架设计哲学的标准解法。它既保障了生产环境 CSRF 防护的完整性,又消除了测试中的非业务干扰,是当前版本下最推荐的 CSRF 测试处理方式。











