CSRF 保护
Spring Security 的 CSRF
Spring Security 默认启用 CSRF 保护。对于前后端分离的 API 项目,这是一个需要特别注意的点。
问题表现
java
// 加了 spring-boot-starter-security 后,不配任何东西
@PostMapping("/api/posts")
public Post create(@RequestBody Post post) {
return postService.save(post);
}浏览器请求这个接口时,会返回 403 Forbidden,控制台日志:
Invalid CSRF Token found for http://localhost:8080/api/posts解决方案
API 项目:直接禁掉(最常见)
java
@Configuration
@EnableWebSecurity
public class SecurityConfig {
@Bean
public SecurityFilterChain filterChain(HttpSecurity http) throws Exception {
http
.csrf(csrf -> csrf.disable()) // 禁用 CSRF
.authorizeHttpRequests(auth -> auth
.anyRequest().permitAll()
);
return http.build();
}
}为什么 API 项目可以禁 CSRF?
- CSRF 攻击依赖浏览器自动携带 Cookie(会话 Cookie)
- API 项目通常用 JWT Token 放在
Authorization头中,不是 Cookie- 不存在自动携带凭证的问题,CSRF 攻击不成立
服务端渲染:保持开启
如果是传统 MVC 项目(Thymeleaf 渲染 HTML),需要 CSRF 保护:
html
<!-- Thymeleaf 模板中自动注入 CSRF Token -->
<form th:action="@{/posts}" method="post">
<input type="hidden" th:name="${_csrf.parameterName}" th:value="${_csrf.token}"/>
<button>提交</button>
</form>Spring Security 会自动在表单中注入 CSRF Token。
⚠️ 注意事项
1. 禁 CSRF 要放在其他配置之前
在高版本的 Spring Security 中,
csrf.disable()的调用顺序有要求。如果同时配置了其他规则,确保 csrf 配置在 authorizeHttpRequests 之前:javahttp .csrf(csrf -> csrf.disable()) // 先禁 CSRF .authorizeHttpRequests(...) // 再配授权
2. Postman/curl 不受 CSRF 影响
CSRF 保护只对浏览器有效。
curl -X POST http://localhost:8080/api/posts不受 CSRF 影响。
3. 纯 API 项目建议统一禁用
如果不确定要不要 CSRF,记住一条规则:Token 认证(JWT)→ 禁用 CSRF;Cookie 认证(Session)→ 启用 CSRF。