我已经配置了 Spring Security(使用 Spring Boot 3.3.2)以遵循 JavaScript 单页应用程序推荐的设置(我们使用 React)。
我设法使用
@WebMvcTest
使我的 .with(csrf())
测试正常工作。这样做的缺点是它使用请求参数,因此它最终出现在我的 Spring Rest Docs 生成的文档的输出中。因此,我想使用 CSRF 令牌作为标头。
如果我使用
.with(csrf().asHeader())
,则 CSRF 检查失败。由于某种原因,CsrfFilter
尝试将 8VkPR8LMFIbrsh2ld-qDcuA84ZnaLjk1AmaCL8CVhLdr6xxNyD87cPupJufGhC2SQce3QtANzKHiTw0YMVOxGvSnvIZe3yV4
之类的值与 UUID 进行比较。
我在https://github.com/spring-projects/spring-security/issues/12774读到我可以创建一个
/csrf
端点,如下所示:
@RestController
@RequestMapping("/csrf")
public class CsrfTokenRestController {
@GetMapping
public CsrfToken getCsrfToken(CsrfToken csrfToken) {
return csrfToken;
}
}
然后使用这样的东西:
MvcResult mvcResult = this.mockMvc.perform(get("/csrf")).andReturn();
Cookie cookie = mvcResult.getResponse().getCookie("XSRF-TOKEN");
this.mockMvc.perform(post("/").header("X-XSRF-TOKEN", cookie.getValue()).cookie(cookie))
.andExpect(status().is2xxSuccessful())
但是,就我而言,响应中没有 cookie。所以这不起作用。
还有什么我可以尝试让这项工作成功吗?
发现问题了。我有多个 SecurityFilterChain bean,而对
/csrf
有效的一个没有像我的 /api/**
端点那样的 csrf 配置。添加相同的配置启用了 cookie,我可以让它工作。