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

Spring Boot3+Spring Security6下测试中CSRF功能失效求助

问题:Spring Security CSRF配置导致单元测试失效

我们遇到Spring Security 6中CSRF保护适配问题,采用官方针对JavaScript框架的解决方案后,基于WebClient和FilterFunction的端到端测试恢复正常,但REST控制器的单元测试出现CSRF令牌不匹配错误,无法正常运行。使用Spring Boot 3之前的CSRF配置可让单元测试正常,但会导致端到端测试失败。

当前CSRF安全配置

// Enable CSRF security
http.csrf { csrfConfigurer ->
    // 适配JavaScript框架的CSRF配置
    val tokenRepository = CookieCsrfTokenRepository.withHttpOnlyFalse()
    val delegate = XorCsrfTokenRequestAttributeHandler()
    // 设置CsrfToken存入的请求属性名
    delegate.setCsrfRequestAttributeName("_csrf")
    // 仅使用XorCsrfTokenRequestAttributeHandler的handle()方法,以及CsrfTokenRequestHandler默认的resolveCsrfTokenValue()实现
    val requestHandler = CsrfTokenRequestHandler(delegate::handle)

    csrfConfigurer.csrfTokenRepository(tokenRepository)
    csrfConfigurer.csrfTokenRequestHandler(requestHandler)
}

修复端到端测试的FilterFunction

override fun filter(request: ClientRequest, next: ExchangeFunction): Mono<ClientResponse> =
    next.exchange(request)
        .flatMap { response: ClientResponse ->
            if (response.statusCode().is4xxClientError) {
                val csrfCookie = response.cookies().getFirst("XSRF-TOKEN")
                if (csrfCookie != null) {
                    val retryRequest: ClientRequest = ClientRequest.from(request)
                        .headers { httpHeaders ->
                            httpHeaders.set("X-XSRF-TOKEN", csrfCookie.value)
                        }
                        .cookies { cookies ->
                            cookies.add("XSRF-TOKEN", csrfCookie.value)
                        }
                        .build()
                    return@flatMap next.exchange(retryRequest)
                }
            }
            Mono.just(response)
        }

失效的单元测试代码

@Test
fun `create tender with copyFrom null should succeed and return 201 and the uuid`() {
    mockMvc
        .perform(
            post("/api/my/endpoint")
                .param("title", "Angebot 1")
                .param("copyFrom", null)
                .with(user(tendererTestUsers[0]))
                .with(csrf())
        )
        .andExpectAll(
            status().isCreated,
            content().contentTypeCompatibleWith(MediaType.APPLICATION_JSON),
            jsonPath("$", `is`(notNullValue()))
        )
}

问题现象

调试确认单元测试中存在CSRF令牌不匹配的问题,推测需要调整测试的CSRF配置,寻求修改思路。

内容的提问来源于stack exchange,提问作者Jan Kohnert

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.09 08:45:31