Spring Security禁用CSRF仍提示无效令牌,POST等请求报403问题
我之前也碰到过一模一样的坑——明明在配置里写了禁用CSRF,结果POST/PUT/DELETE请求还是被CsrfFilter拦下来返回403,而且认证明明已经通过了。结合你的配置和问题描述,给你几个排查和解决的方向:
1. 修正配置链式调用的写法(最可能的原因)
你当前的配置把csrf().disable()单独拆成了一行,这种写法在某些Spring Security版本中可能导致配置没有全局生效。正确的做法是把csrf().disable()整合到完整的链式配置中,确保所有后续的配置都继承这个禁用规则:
protected void configure(HttpSecurity http) throws Exception { http .csrf().disable() // 关键:把禁用CSRF放在链式配置的最开头 .httpBasic() .and() .authorizeRequests() .antMatchers(HttpMethod.POST, "/user/add").hasRole("ADMIN") .antMatchers(HttpMethod.POST, HttpMethod.DELETE).hasAnyRole("ADMIN", "TRAINER") .antMatchers(HttpMethod.GET, HttpMethod.PUT, HttpMethod.HEAD).permitAll() // 合并写法更简洁 .antMatchers("/register/").authenticated() .and() .formLogin().permitAll() .and() .logout().permitAll() .and() .exceptionHandling(); }
单独调用http.csrf().disable()后,返回的是CsrfConfigurer对象,而你后续又重新调用http.httpBasic(),可能导致CSRF禁用的配置没有被正确绑定到整个Security链上。链式写法能确保所有配置都基于同一个HttpSecurity实例生效。
2. 排查是否存在其他冲突的Security配置
如果你的项目里还有其他WebSecurityConfigurerAdapter子类(或者Spring Security 5.7+的SecurityFilterChain Bean),要检查它们的优先级:
- 带有
@Order注解的配置类会优先生效,如果高优先级的配置没有禁用CSRF,就会覆盖你的当前配置。 - 确保所有Security配置类都统一禁用了CSRF,或者调整Order让你的配置优先级最高。
3. 验证CsrfFilter是否真的被禁用
启动应用时查看日志,如果看到CsrfFilter被初始化的日志,说明禁用操作没生效。正常情况下,禁用CSRF后Spring Security不会加载这个过滤器。
4. (可选)升级到Spring Security 5.7+的新配置方式
如果你用的是Spring Security 5.7及以上版本,建议废弃WebSecurityConfigurerAdapter,改用基于组件的SecurityFilterChain配置,这种写法更清晰,不容易出现链式调用的问题:
@Bean public SecurityFilterChain filterChain(HttpSecurity http) throws Exception { http .csrf(csrf -> csrf.disable()) .httpBasic(Customizer.withDefaults()) .authorizeRequests(auth -> auth .antMatchers(HttpMethod.POST, "/user/add").hasRole("ADMIN") .antMatchers(HttpMethod.POST, HttpMethod.DELETE).hasAnyRole("ADMIN", "TRAINER") .antMatchers(HttpMethod.GET, HttpMethod.PUT, HttpMethod.HEAD).permitAll() .antMatchers("/register/").authenticated() ) .formLogin(form -> form.permitAll()) .logout(logout -> logout.permitAll()) .exceptionHandling(Customizer.withDefaults()); return http.build(); }
最后排查Postman请求
虽然概率很低,但可以检查下Postman是否不小心携带了X-XSRF-TOKEN这类CSRF相关的请求头——不过如果CSRF已经正确禁用,即使有这个头也不会触发校验,这一步主要是排除干扰。
内容的提问来源于stack exchange,提问作者vbknez




