You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Spring Security 6中使用MockMvc实现推荐CSRF保护的配置问题

解决方案

针对你遇到的Spring Security CSRF测试问题,这里提供两种可行方案:

方案一:手动生成CSRF Token并通过Header传递

在测试类中直接利用CsrfTokenRepository生成符合要求的Token,避免依赖端点获取,步骤如下:

  1. 确保测试类加载完整的Security配置和目标控制器
@WebMvcTest(YourTargetController.class)
@Import(SecurityConfig.class) // 导入你的Spring Security配置类
class YourControllerTest {

    @Autowired
    private MockMvc mockMvc;

    @Autowired
    private CsrfTokenRepository csrfTokenRepository;

    @Test
    void postRequestWithCsrfHeader() throws Exception {
        // 生成CSRF Token并模拟存储逻辑
        MockHttpServletRequest request = new MockHttpServletRequest();
        CsrfToken csrfToken = csrfTokenRepository.generateToken(request);
        request.setAttribute(CsrfToken.class.getName(), csrfToken);
        csrfTokenRepository.saveToken(csrfToken, request, new MockHttpServletResponse());

        // 发起POST请求,携带Header和Cookie
        mockMvc.perform(post("/")
                        .header(csrfToken.getHeaderName(), csrfToken.getToken())
                        .cookie(new Cookie(csrfToken.getCookieName(), csrfToken.getToken())))
                .andExpect(status().is2xxSuccessful());
    }
}

方案二:修复/csrf端点测试无法获取Cookie的问题

如果坚持通过/csrf端点获取Token,需确保测试类加载了该端点和完整的Security配置:

  1. 调整测试类的注解范围
@WebMvcTest({YourTargetController.class, CsrfTokenRestController.class})
@Import(SecurityConfig.class)
class YourControllerTest {

    @Autowired
    private MockMvc mockMvc;

    @Autowired
    private ObjectMapper objectMapper;

    @Test
    void postRequestWithCsrfFromEndpoint() throws Exception {
        // 请求/csrf端点获取Token和Cookie
        MvcResult csrfResult = mockMvc.perform(get("/csrf"))
                .andExpect(status().isOk())
                .andReturn();

        // 提取XSRF-TOKEN Cookie
        Cookie xsrfCookie = csrfResult.getResponse().getCookie("XSRF-TOKEN");
        // 从响应体解析Token(也可直接用Cookie的值)
        CsrfToken token = objectMapper.readValue(csrfResult.getResponse().getContentAsString(), CsrfToken.class);

        // 发起POST请求
        mockMvc.perform(post("/")
                        .header("X-XSRF-TOKEN", xsrfCookie.getValue())
                        .cookie(xsrfCookie))
                .andExpect(status().is2xxSuccessful());
    }
}

关键配置检查

确保你的Security配置正确启用了Cookie-based CSRF保护:

@Configuration
@EnableWebSecurity
public class SecurityConfig {

    @Bean
    public SecurityFilterChain securityFilterChain(HttpSecurity http) throws Exception {
        http
                .csrf(csrf -> csrf
                        .csrfTokenRepository(CookieCsrfTokenRepository.withHttpOnlyFalse()) // 允许前端读取Cookie
                )
                // 其他安全配置...
        return http.build();
    }
}

Spring Rest Docs 补充说明

如果不想让CSRF Token出现在文档的请求参数中,可通过Rest Docs忽略参数:

this.mockMvc.perform(post("/"))
        .andDo(document("post-endpoint",
                requestParameters(
                        parameterWithName("_csrf").ignored()
                )
        ));

或者直接在文档中说明:请求需携带X-XSRF-TOKEN请求头,同时客户端需持有XSRF-TOKEN Cookie。

内容的提问来源于stack exchange,提问作者Wim Deblauwe

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.19 06:00:02