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

Spring Security在Thymeleaf中无法注入CSRF参数问题求助

解决方案

1. 修复Thymeleaf中CSRF Token的获取方式

Spring WebFlux作为反应式框架,CSRF Token的存储与传递逻辑和传统Servlet环境不同,无法直接通过${_csrf}访问。需要借助Thymeleaf的#exchange对象获取ServerWebExchange实例,进而拿到CSRF Token:

修改表单中的CSRF隐藏字段为:

<th:block th:with="csrfToken=${#exchange.getAttribute('org.springframework.security.web.server.csrf.CsrfToken')}">
    <input type="hidden" th:name="${csrfToken.parameterName}" th:value="${csrfToken.token}" />
</th:block>

或者使用内联简化写法:

<input type="hidden" 
       th:name="${#exchange.getAttribute('org.springframework.security.web.server.csrf.CsrfToken').parameterName}" 
       th:value="${#exchange.getAttribute('org.springframework.security.web.server.csrf.CsrfToken').token}" />

2. 添加登录页面的GET请求控制器

当前缺少处理/login路径的GET请求控制器,需新增方法渲染登录页面:

@GetMapping("/login")
public Mono<String> showLoginPage() {
    return Mono.just("login"); // 对应你的登录页面模板文件名(无需.html后缀)
}

3. 优化Security配置

你的配置中同时启用了httpBasic和formLogin,若不需要HTTP基础认证,可移除.httpBasic()以避免潜在冲突:

@Bean
public SecurityWebFilterChain securityWebFilterChain(ServerHttpSecurity http) {
    http
        .authorizeExchange()
            .pathMatchers("/login").permitAll() 
            .pathMatchers("/api/alumnos/getAlumnos","/listar","/","/index").hasRole("USER")
            .pathMatchers("/api/alumnos/saveAlumno","/saveAlumno").hasRole("FUNCIONAL")
            .anyExchange().authenticated()
        .and().csrf(csrf -> csrf.csrfTokenRepository(CookieServerCsrfTokenRepository.withHttpOnlyFalse()))
        .formLogin()
        .loginPage("/login");

    return http.build();
}

原理说明

Spring WebFlux中,CSRF Token由CookieServerCsrfTokenRepository存储在Cookie中,同时ServerWebExchange会持有该Token的引用。Thymeleaf通过#exchange对象访问ServerWebExchange,即可获取到CSRF Token的参数名和值,从根本解决_csrf对象为null的问题。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.13 15:55:14