Spring Security CSRF 与 CORS
CSRF 和 CORS 经常被混在一起。CSRF 是防止用户在已登录状态下被第三方网站诱导发起危险请求;CORS 是浏览器限制跨域读取响应的安全策略。
区别
| 项目 | CSRF | CORS |
|---|---|---|
| 解决问题 | 防止跨站请求伪造 | 控制浏览器跨域访问 |
| 发生位置 | 服务端校验请求可信度 | 浏览器和服务端协商 |
| 常见场景 | Cookie Session 登录 | 前后端分离跨域调用 |
| 配置结果 | 拒绝缺少 CSRF Token 的请求 | 返回跨域响应头 |
CORS 预检流程
mermaid
sequenceDiagram
participant B as 浏览器
participant S as 服务端
B->>S: OPTIONS 预检请求
S-->>B: Access-Control-Allow-Origin 等响应头
B->>S: 真实业务请求
S-->>B: 业务响应CSRF 校验流程
mermaid
flowchart TD
A[危险请求] --> B{是否需要CSRF保护}
B -- 否 --> C[继续过滤器链]
B -- 是 --> D{Token是否匹配}
D -- 是 --> C
D -- 否 --> E[拒绝请求]配置建议
- 传统 Session + Cookie 登录,建议开启 CSRF。
- 纯 Token 鉴权且 Token 放在
Authorization请求头中,通常可以关闭 CSRF。 - CORS 不要简单配置
*加凭证,带 Cookie 时必须指定明确 Origin。 - 预检请求要允许
OPTIONS,否则浏览器会在真实请求前失败。 - 网关层和应用层不要重复写冲突的跨域响应头。
排查顺序
跨域问题先看浏览器控制台,再看响应头。401/403 是鉴权问题,CORS 报错是浏览器拦截问题,两者处理方向不同。
配置 Demo:前后端分离 CORS
java
@Bean
public SecurityFilterChain securityFilterChain(HttpSecurity http) throws Exception {
http
.cors(Customizer.withDefaults())
.csrf(csrf -> csrf.disable())
.authorizeHttpRequests(auth -> auth
.requestMatchers("/api/admin/login").permitAll()
.anyRequest().authenticated()
);
return http.build();
}
@Bean
public CorsConfigurationSource corsConfigurationSource() {
CorsConfiguration config = new CorsConfiguration();
config.setAllowedOrigins(List.of("http://localhost:5173"));
config.setAllowedMethods(List.of("GET", "POST", "PUT", "DELETE", "OPTIONS"));
config.setAllowedHeaders(List.of("Authorization", "Content-Type"));
config.setAllowCredentials(true);
UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource();
source.registerCorsConfiguration("/**", config);
return source;
}如果 Token 放在 Authorization 请求头里,通常可以关闭 CSRF;如果使用 Cookie Session 登录,则要重新评估 CSRF 防护。
