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

Spring Security配置CSRF后非GET请求触发403错误的解决咨询

问题原因分析

Spring Security默认开启CSRF(跨站请求伪造)防护机制,核心目的是拦截恶意站点通过浏览器自动携带用户Cookie发起的未授权修改请求。

对于POST/PUT/DELETE这类会修改服务器数据的非幂等请求,Spring Security会强制校验请求中是否包含有效的CSRF Token:

  • 你的请求中没有携带该Token,即使已经通过ADMIN身份认证,也会被CSRF过滤器判定为非法请求,返回403 Forbidden。
  • 而GET请求属于幂等请求,不会触发CSRF校验,所以ADMIN和USER角色都能正常访问。
安全解决方案

不要全局禁用CSRF(会带来安全风险),可以根据你的API使用场景选择以下安全方案:

1. 针对浏览器端请求:携带CSRF Token

如果你的API是供前端浏览器调用:

  • 表单提交场景:在表单中添加Spring Security自动生成的CSRF Token隐藏域:
    <form method="post" action="/topics">
        <input type="hidden" name="_csrf" value="${_csrf.token}"/>
        <!-- 其他表单字段 -->
    </form>
    
  • AJAX/REST请求场景:
    1. 前端先从Cookie中读取名为XSRF-TOKEN的CSRF Token(Spring Security默认会将Token写入该Cookie);
    2. 在非GET请求的请求头中添加X-XSRF-TOKEN字段,值为读取到的Token。示例(JavaScript):
      const token = document.cookie.split('; ')
          .find(row => row.startsWith('XSRF-TOKEN='))
          ?.split('=')[1];
      
      fetch('/topics', {
          method: 'POST',
          headers: {
              'X-XSRF-TOKEN': token,
              'Content-Type': 'application/json'
          },
          body: JSON.stringify(/* 请求体 */)
      });
      

2. 针对非浏览器客户端:精准禁用CSRF

如果你的API仅供移动端、后端服务等非浏览器客户端调用(这类场景不存在CSRF攻击风险),可以仅对API路径禁用CSRF,保留其他路径的防护:

@Bean
public SecurityFilterChain filterChain(HttpSecurity http) throws Exception {
    http.authorizeRequests()
        .antMatchers(HttpMethod.GET,"/topics*").hasAnyRole("USER","ADMIN")
        .antMatchers(HttpMethod.POST,"/topics*").hasRole("ADMIN")
        .antMatchers(HttpMethod.PUT,"/topics*").hasRole("ADMIN")
        .antMatchers(HttpMethod.DELETE,"/topics*").hasRole("ADMIN")
        .antMatchers(HttpMethod.GET,"/hellos*").hasRole("ADMIN")
        .and()
        .formLogin().and().httpBasic()
        // 仅对指定API路径禁用CSRF
        .and().csrf(csrf -> csrf.ignoringAntMatchers("/topics*", "/hellos*"));

    return http.build();
}

3. 无状态认证场景(如JWT):调整CSRF策略

如果你的系统采用JWT这类无状态认证方式(Token存储在前端本地而非Cookie),CSRF攻击风险极低,可以结合配置优化:

@Bean
public SecurityFilterChain filterChain(HttpSecurity http) throws Exception {
    http.authorizeRequests()
        // 权限配置不变
        .antMatchers(HttpMethod.GET,"/topics*").hasAnyRole("USER","ADMIN")
        .antMatchers(HttpMethod.POST,"/topics*").hasRole("ADMIN")
        .antMatchers(HttpMethod.PUT,"/topics*").hasRole("ADMIN")
        .antMatchers(HttpMethod.DELETE,"/topics*").hasRole("ADMIN")
        .antMatchers(HttpMethod.GET,"/hellos*").hasRole("ADMIN")
        .and()
        .formLogin().and().httpBasic()
        // 配置CSRF Token存储方式,同时对JWT认证的API路径禁用CSRF
        .and().csrf(csrf -> csrf
            .csrfTokenRepository(CookieCsrfTokenRepository.withHttpOnlyFalse())
            .ignoringAntMatchers("/api/**") // 替换为你的JWT API路径
        );

    return http.build();
}

内容的提问来源于stack exchange,提问作者Ravi teja thumnoori

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.30 05:37:48