Spring Security 5.2.3环境下注册表单CSRF Token未在UI中渲染的问题求助
别着急,咱们一步步排查这个问题,大概率是配置或者页面设置的小细节没到位:
1. 先确认Spring Security的CSRF功能没被禁用
Spring Security默认是开启CSRF防护的,但如果你在Security配置类里手动加了csrf().disable(),那_csrf对象就不会被注入到请求中。检查你的配置类:
@Configuration @EnableWebSecurity public class SecurityConfig extends WebSecurityConfigurerAdapter { @Override protected void configure(HttpSecurity http) throws Exception { http .authorizeRequests() .anyRequest().permitAll() // 根据你的需求调整权限 .and() // 确保这里没有csrf().disable(),如果需要用Cookie存储Token可以加下面的配置 .csrf() .csrfTokenRepository(CookieCsrfTokenRepository.withHttpOnlyFalse()); } }
如果之前加了csrf().disable(),去掉它就能让Spring自动生成并注入CSRF Token了。
2. 确保JSP页面启用了EL表达式
如果JSP忽略了EL表达式,${_csrf.parameterName}和${_csrf.token}会原样输出,不会被解析成实际的Token值。在你的registration.jsp开头加上这句:
<%@ page isELIgnored="false" %>
这是很多新手容易踩的坑,一定要确认这个设置。
3. 确认注册页面的请求路径受Spring Security保护
如果你的registration.jsp对应的请求路径被Spring Security忽略了(比如用了web.ignoring().antMatchers("/registration")),那Spring不会给这个请求注入_csrf对象。检查配置类里的configure(WebSecurity web)方法,确保注册路径没有被加入忽略列表:
@Override public void configure(WebSecurity web) throws Exception { // 只忽略静态资源,不要把注册页面加进来 web.ignoring().antMatchers("/css/**", "/js/**"); }
只有受Spring Security处理的请求,才会自动生成并传递CSRF Token。
4. 试试用Spring表单标签自动生成CSRF字段
你已经用了Spring的<form:form>标签,其实它会自动帮你生成CSRF的隐藏输入字段,不需要手动添加。可以先把你手动加的<input type="hidden"...>删掉,然后查看页面源码,应该能看到类似这样的自动生成字段:
<input type="hidden" name="_csrf" value="xxxxxx-xxxx-xxxx-xxxx-xxxxxxxxx"/>
如果自动生成成功,说明之前手动添加的写法可能有问题(比如路径或者EL解析的问题),用自动生成的方式更可靠。
5. 调试确认_csrf对象是否存在
可以在JSP里加一段调试代码,看看_csrf对象有没有被正确注入:
<!-- 调试用,看完可以删掉 --> <div style="display:none;"> CSRF Parameter Name: ${_csrf.parameterName}<br/> CSRF Token: ${_csrf.token} </div>
如果这段输出是空的,说明_csrf对象根本没出现在请求属性里,回到前面的步骤检查配置;如果有值,那就是你手动添加的隐藏字段写法有问题,改用自动生成的方式即可。
按照上面的步骤排查,应该就能解决Token不渲染的问题了。
内容的提问来源于stack exchange,提问作者Jay

