You need to enable JavaScript to run this app.
最新活动
大模型
产品
解决方案
定价
生态与合作
支持与服务
开发者
了解我们

Spring Security禁用CSRF仍提示无效令牌,POST等请求报403问题

解决Spring Security已禁用CSRF但仍触发令牌校验的问题

我之前也碰到过一模一样的坑——明明在配置里写了禁用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

火山引擎 最新活动