
在 Spring Boot 3 + Spring Security 6+ 的测试中,无需全局关闭 CSRF 防护,只需在 MockMvc 请求中显式添加 .with(csrf()) 即可安全通过校验,既保持生产环境安全性,又确保单元测试可运行。
在 spring boot 3 + spring security 6+ 的测试中,无需全局关闭 csrf 防护,只需在 mockmvc 请求中显式添加 `.with(csrf())` 即可安全通过校验,既保持生产环境安全性,又确保单元测试可运行。
在 Spring Boot 3.x(对应 Spring Security 6.1+)中,CSRF 保护默认启用,且对所有非幂等请求(如 POST、PUT、DELETE)强制校验令牌。但值得注意的是:GET 请求本身不受 CSRF 保护拦截——你提到测试返回 406 Not Acceptable 而非 403 Forbidden,说明问题并非 CSRF 拦截所致(CSRF 失败必报 403),而是内容协商(Content Negotiation)或响应格式配置异常(如缺少 @ResponseBody、produces 不匹配、MessageConverter 缺失等)。不过,若后续测试涉及 POST/PUT/DELETE 等操作,CSRF 就成为关键障碍。
✅ 正确解法:不关闭 CSRF,而是为测试请求提供合法令牌
Spring Security 提供了开箱即用的测试支持类 SecurityMockMvcRequestPostProcessors,其中 csrf() 方法会自动注入一个有效、签名的 CSRF Token 到请求中(模拟真实表单提交行为),完全兼容 SecurityFilterChain 配置,且不影响生产环境安全策略。
✅ 推荐做法:在测试中使用 .with(csrf())
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 支持(即使 GET 不校验,也无害且兼容)
).andExpect(status().isOk());
}
? 补充说明:虽然
GET请求默认不触发 CSRF 校验(因属安全方法),但MockMvc在启用 CSRF 保护时,会对所有请求执行CsrfFilter的前置检查逻辑(如解析 token 存储机制)。添加.with(csrf())可避免潜在的 token 解析异常或空指针风险,提升测试健壮性;对POST等请求则是必需操作。
⚠️ 不推荐的做法(已过时或存在风险)
❌ 在测试配置中覆盖
SecurityFilterChain并调用.csrf(csrf -> csrf.disable())
→ 这会彻底关闭 CSRF,丧失测试真实性,且易导致“测试通过、生产报 403”的线上事故。❌ 使用
@TestConfiguration替换生产安全配置 Bean
→ 增加维护成本,违反“测试应贴近生产”原则,且可能掩盖配置差异引发的集成问题。❌ 修改
application-test.yml中设置spring.security.csrf.enabled=false
→ Spring Boot 3+ 不再支持该配置项(spring.security.csrf.*属性已被移除),该配置无效。
? 进阶提示:确保依赖与导入正确
请确认测试类中已正确引入相关类(Spring Security Test 模块需在 classpath 中):
<!-- pom.xml --> <dependency><groupid>org.springframework.security</groupid><artifactid>spring-security-test</artifactid><scope>test</scope></dependency>
同时检查静态导入是否完整:
import static org.springframework.security.test.web.servlet.request.SecurityMockMvcRequestPostProcessors.csrf; // 注意:不是旧版的 org.springframework.security.test.web.servlet.request.SecurityRequestPostProcessors
✅ 总结
| 场景 | 推荐方案 |
|---|---|
| 单元测试(MockMvc) | 使用 .with(csrf())(最轻量、最安全、最标准) |
| 集成测试(@SpringBootTest + WebEnvironment.RANDOM_PORT) | 同样适用 .with(csrf());若需模拟真实浏览器行为,可配合 @AutoConfigureMockMvc(addFilters = false) 临时绕过 Filter 链(慎用) |
| 生产环境 REST API | 显式禁用 CSRF(.csrf(csrf -> csrf.disable())),前提是采用无状态认证(如 Bearer Token / Basic Auth)且不依赖 Cookie 会话 |
| 前后端分离应用(如 Vue/React) | 推荐 CookieCsrfTokenRepository.withHttpOnlyFalse(),前端从 XSRF-TOKEN cookie 读取并携带至 X-XSRF-TOKEN 请求头 |
遵循这一实践,你既能保障生产环境的安全水位,又能写出稳定、可信赖、符合 Spring Security 最新范式的测试代码。











