Spring Boot结合Spring Security配置公共端点GET正常但POST报403
问题现象
基于Spring Boot搭建的接口服务,配置了全局接口鉴权规则:仅指定公开路径允许无JWT令牌访问,其余所有接口必须通过JWT身份校验才可访问。
当前配置下,GET方法访问公开路径运行完全正常,但使用POST方法访问同一公开路径时,会直接返回HTTP 403 Forbidden,请求未进入身份校验环节就被拦截。
现有代码配置
Spring 安全配置类
@Configuration @EnableGlobalMethodSecurity(prePostEnabled = true) public class SecurityConfiguration extends WebSecurityConfigurerAdapter { private static final String[] PUBLIC_RESOURCES = { "/", "/user/login" }; @Override protected void configure(final HttpSecurity httpSecurity) throws Exception { httpSecurity .antMatcher("/**").authorizeRequests() .antMatchers(PUBLIC_RESOURCES).permitAll() .anyRequest().authenticated(); } }
对应接口控制器
@RestController @RequestMapping(path = "user") public class LoginController { @GetMapping public String get() { return "Hey, Joe (get)"; } @PostMapping public String post() { return "Hey, Joe (post)"; } }
问题根因
该拦截与路径权限配置逻辑无关,核心原因是Spring Security默认开启的CSRF跨站请求伪造防护机制:
- 默认规则下,CSRF过滤器会拦截所有非幂等的写操作请求(POST、PUT、DELETE等),要求请求携带合法的CSRF令牌
- 该校验环节优先级高于路径权限匹配逻辑,哪怕对应路径配置了
permitAll,只要请求未携带合法CSRF令牌,就会被CSRF过滤器直接拦截返回403 - GET、HEAD、OPTIONS、TRACE这类幂等请求属于CSRF规则默认放行的范围,因此可以正常穿透校验完成访问
适配方案
根据项目实际场景,可以选择以下两种调整方式:
- 如果当前服务是纯前后端分离的接口服务,不依赖Cookie维护会话状态,可以直接在安全配置中关闭CSRF防护,原有路径鉴权规则保持不变即可。调整后的配置参考:
@Override protected void configure(final HttpSecurity httpSecurity) throws Exception { httpSecurity // 关闭CSRF防护 .csrf().disable() .antMatcher("/**").authorizeRequests() .antMatchers(PUBLIC_RESOURCES).permitAll() .anyRequest().authenticated(); }
- 如果需要保留CSRF防护能力,需要在交互流程中先从服务端获取CSRF令牌,再在所有POST类写操作的请求头或表单参数中携带该令牌,通过CSRF校验后即可正常访问对应路径。
内容的提问来源于stack exchange,提问作者Robert Strauch
相关产品推荐
相关产品推荐

