开启Spring Security CSRF防护后所有非GET请求被禁止的问题
问题分析与解决方案
你的问题核心在于无状态JWT会话模式与Spring Security默认CSRF机制不兼容:
- Spring Security默认将CSRF Token存储在
HttpSession中,但你设置了SessionCreationPolicy.STATELESS,服务器不会创建或使用会话,因此无法生成和返回CSRF Token; - 所有非GET/HEAD/OPTIONS请求都会被CSRF过滤器拦截,哪怕是无需认证的请求,因为缺少有效的Token验证。
解决方案一:对公开接口跳过CSRF验证
如果部分非GET请求是公开接口(无需认证),可以直接跳过这些路径的CSRF校验,修改configure(HttpSecurity http)方法:
@Override protected void configure(HttpSecurity http) throws Exception { http .csrf() .ignoringAntMatchers("/public/**", "/login") // 替换为你的公开非GET请求路径 .and() .authorizeRequests() .antMatchers("/profile").authenticated() .antMatchers("/admin/**").hasRole("ADMIN") .anyRequest().permitAll() .and() .sessionManagement().sessionCreationPolicy(SessionCreationPolicy.STATELESS) .and() .headers().frameOptions().disable() .and() .exceptionHandling() .authenticationEntryPoint(new HttpStatusEntryPoint(HttpStatus.UNAUTHORIZED)); http.addFilterBefore(jwtRequestFilter, UsernamePasswordAuthenticationFilter.class); }
解决方案二:配置CSRF Token存储到Cookie(适合前后端分离场景)
如果需要对所有非GET请求做CSRF防护,可将CSRF Token存储到Cookie中,允许前端读取并在请求时携带,修改配置如下:
首先导入CookieCsrfTokenRepository:
import org.springframework.security.web.csrf.CookieCsrfTokenRepository;
然后修改configure(HttpSecurity http)中的CSRF配置:
@Override protected void configure(HttpSecurity http) throws Exception { http .csrf() .csrfTokenRepository(CookieCsrfTokenRepository.withHttpOnlyFalse()) // 允许前端读取Cookie .and() .authorizeRequests() .antMatchers("/profile").authenticated() .antMatchers("/admin/**").hasRole("ADMIN") .anyRequest().permitAll() .and() .sessionManagement().sessionCreationPolicy(SessionCreationPolicy.STATELESS) .and() .headers().frameOptions().disable() .and() .exceptionHandling() .authenticationEntryPoint(new HttpStatusEntryPoint(HttpStatus.UNAUTHORIZED)); http.addFilterBefore(jwtRequestFilter, UsernamePasswordAuthenticationFilter.class); }
前端配合处理
前端需要从Cookie中取出XSRF-TOKEN值,在非GET请求的请求头中添加X-XSRF-TOKEN,值为Cookie中的Token内容。例如:
- 原生JS:从
document.cookie中提取XSRF-TOKEN - Axios:框架会自动读取
XSRF-TOKENCookie,并自动添加X-XSRF-TOKEN请求头
这样Spring Security会自动验证请求头中的Token与Cookie中的Token是否一致,完成CSRF防护。
内容的提问来源于stack exchange,提问作者CyberLight 64
相关产品推荐
相关产品推荐

