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
相关产品推荐
相关产品推荐

