Spring Boot微服务REST端点遇403 CSRF会话未找到错误求助
搞定这个403 CSRF错误其实很简单!
老哥,我一眼就看穿问题根源了:你的Spring Security默认给所有非GET请求(POST/PUT/DELETE这些)都开了CSRF防护,但你的REST服务用的是HMAC认证,根本没有会话(session)——而CSRF token是和会话绑定的,所以当REST接口收到非GET请求时,Security找不到对应的会话来验证token,直接就返回403了。
下面给你几个实用的解决方案,按优先级排序:
方案1:给REST端点单独关掉CSRF(最推荐)
既然你的REST服务已经用HMAC做认证了,CSRF防护完全是多余的——HMAC本身就防了这类跨站攻击。直接在Security配置里把REST路径排除在CSRF检查外就行:
import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.security.config.annotation.web.builders.HttpSecurity; import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity; import org.springframework.security.web.SecurityFilterChain; @Configuration @EnableWebSecurity public class SecurityConfig { @Bean public SecurityFilterChain securityFilterChain(HttpSecurity http) throws Exception { http // 先配置网站端的权限规则 .authorizeHttpRequests(auth -> auth .requestMatchers("/serverwebpages/**").authenticated() // 网站页面需要登录 .requestMatchers("/api/restendpoints/**").permitAll() // REST接口先放开,后面结合HMAC认证 .anyRequest().authenticated() ) // 重点:给REST路径关闭CSRF检查 .csrf(csrf -> csrf .ignoringRequestMatchers("/api/restendpoints/**") ) // 网站端的登录配置(比如你的表单登录) .formLogin(form -> form .loginPage("/serverwebpages/login") .permitAll() ); // 别忘了把你的HMAC认证过滤器加进来,放在合适的位置(比如用户名密码过滤器之前) // http.addFilterBefore(yourHmacAuthFilter(), UsernamePasswordAuthenticationFilter.class); return http.build(); } }
方案2:硬要保留CSRF?可以试试无会话存储(不推荐)
如果你执念非要给REST加CSRF(真的没必要),可以用Cookie存储CSRF token,不需要会话绑定,但这样客户端每次请求都得带这个token,完全是多此一举。代码大概是这样:
.csrf(csrf -> csrf .csrfTokenRepository(CookieCsrfTokenRepository.withHttpOnlyFalse()) // 还是建议忽略REST路径,除非你真的需要 // .ignoringRequestMatchers("/api/restendpoints/**") )
不过真心不建议这么干,HMAC已经足够安全了,画蛇添足反而增加复杂度。
方案3:调整过滤器顺序(辅助方案)
如果你的HMAC是自定义过滤器,要确保它在CsrfFilter之前执行——这样HMAC验证通过后,Security就不会再去检查CSRF了。但即使这样,没有会话的情况下CSRF还是会报错,所以最好还是结合方案1一起用。
最后提醒几个关键点
- 一定要把网站和REST的安全规则分开:网站要会话、CSRF、表单登录;REST要无会话、HMAC、无CSRF。
- 确认
ignoringRequestMatchers的路径和你的REST端点完全匹配,比如/api/restendpoints/**能覆盖所有子路径。 - 测试的时候先单独关掉REST的CSRF,验证非GET请求正常了,再调整HMAC的配置,一步一步来。
内容的提问来源于stack exchange,提问作者skmansfield
相关产品推荐
相关产品推荐

