使用@WebMvcTest测试POST接口返回403,如何在测试中禁用CSRF?
解决Spring MVC测试中CSRF禁用仍返回403的问题
问题根源
你的测试代码存在两处冲突配置,导致WebSecurityConfig里的CSRF禁用设置未生效:
- 你添加了
@AutoConfigureMockMvc(addFilters = false),本意是禁用过滤器,但又在setup()里手动添加springSecurityFilterChain并调用apply(springSecurity()),这会强制加载默认的Spring Security过滤器链,其中包含CSRF过滤器。 @WebMvcTest默认仅加载控制器相关Bean,不会自动加载你的WebSecurityConfig类,导致其中的CSRF禁用配置未被应用到测试环境。
解决方案
方案一:简化MockMvc配置,加载自定义Security配置
删除手动构建MockMvc的代码,直接让Spring自动配置,并指定加载你的安全配置类:
@WebMvcTest(controllers = AuthController.class) @Import(WebSecurityConfig.class) // 加载自定义安全配置 public class AuthControllerTest { @Autowired private MockMvc mockMvc; // 直接注入自动配置好的MockMvc // 其他依赖注入保持不变... // 移除自定义的setup()方法 }
方案二:手动构建MockMvc时全局禁用CSRF
如果需要手动构建MockMvc,可在构建时明确全局禁用CSRF:
@BeforeEach public void setup() { mockMvc = MockMvcBuilders .webAppContextSetup(context) .apply(springSecurity()) .defaultRequest(get("/").with(csrf().disable())) // 全局禁用CSRF .build(); }
方案三:单个请求中临时禁用CSRF
针对特定POST请求,在调用时单独禁用CSRF:
@Test public void givenTalentRegister_whenValidUrlAndContentType_thenReturns200() throws Exception { CreateTalent createTalent = new CreateTalent("test@mail.com", "123456", "Name", "Surname", "Java Developer"); mockMvc.perform(post("/talents/register") .content(objectMapper.writeValueAsString(createTalent)) .characterEncoding("utf-8") .contentType("application/json") .with(csrf().disable())) // 单个请求禁用CSRF .andDo(print()) .andExpect(status().isOk()); }
方案四:移除冲突注解
删除@AutoConfigureMockMvc(addFilters = false),该注解与你手动添加过滤器的操作冲突,同时确保加载自定义安全配置:
@WebMvcTest(controllers = AuthController.class) @Import(WebSecurityConfig.class) public class AuthControllerTest { @Autowired private MockMvc mockMvc; // ... 其他代码 }
验证方式
测试时观察日志,若不再出现o.s.security.web.csrf.CsrfFilter: Invalid CSRF token found的输出,说明CSRF禁用配置已生效。
内容的提问来源于stack exchange,提问作者Mark
相关产品推荐
相关产品推荐

