清除Cookie后如何获取XSRF Token?Spring Security+Angular7场景求解
问题分析
你的核心问题在于:Angular的默认XSRF拦截器仅当浏览器已存在XSRF-TOKEN Cookie时,才会自动在请求头中添加X-XSRF-TOKEN;首次访问时Cookie为空,第一个POST请求因缺少该头被Spring Security拦截返回403。另外,浏览器的OPTIONS预检请求仅针对跨域非简单请求触发,同域下的POST请求属于简单请求,不会自动发起OPTIONS,你的预期不符合浏览器同源策略规则。
最优解决方案
最简洁可靠的方式是:在Angular应用初始化阶段,先发起一个无副作用的GET请求获取XSRF-TOKEN Cookie,再执行后续的业务POST请求。Spring Security会自动在任何合法HTTP请求的响应中注入XSRF-TOKEN Cookie,只需确保这个GET请求能被正常处理即可。
1. Angular端实现
在根组件的初始化钩子中,先调用简单GET接口获取Cookie,再启动业务请求:
import { Component, OnInit } from '@angular/core'; import { HttpClient } from '@angular/common/http'; @Component({ selector: 'app-root', templateUrl: './app.component.html' }) export class AppComponent implements OnInit { constructor(private readonly http: HttpClient) {} ngOnInit(): void { // 先获取XSRF-TOKEN Cookie this.http.get('/api/csrf-token', { responseType: 'text' }).subscribe({ next: () => this.initBusinessOperations(), error: err => console.error('获取CSRF Token失败:', err) }); } private initBusinessOperations(): void { // 放置原本的首次POST请求逻辑 this.http.post('/api/your-business-api', { /* 请求体 */ }).subscribe(); } }
2. Spring Boot后端配置
添加一个空的GET接口(无需业务逻辑),供前端获取Cookie:
@RestController @RequestMapping("/api") public class CsrfTokenController { @GetMapping("/csrf-token") public ResponseEntity<Void> getCsrfToken() { // Spring Security会自动在响应中设置XSRF-TOKEN Cookie return ResponseEntity.ok().build(); } }
同时确保Spring Security的CSRF配置正确,允许匿名访问该GET接口(若应用支持匿名访问):
@Configuration @EnableWebSecurity public class SecurityConfig { @Bean public SecurityFilterChain securityFilterChain(HttpSecurity http) throws Exception { http .csrf(csrf -> csrf .csrfTokenRepository(CookieCsrfTokenRepository.withHttpOnlyFalse()) // 确保XSRF-TOKEN Cookie可被Angular读取 ) .authorizeHttpRequests(auth -> auth .requestMatchers(HttpMethod.GET, "/api/csrf-token").permitAll() // 允许匿名访问获取CSRF Token的接口 .anyRequest().authenticated() ); return http.build(); } }
补充说明
- 无需修改Angular的默认XSRF拦截器,一旦
XSRF-TOKENCookie存在,拦截器会自动在后续POST/PUT/DELETE请求中添加X-XSRF-TOKEN头。 - 不要通过放宽Spring Security的CSRF校验绕过问题,这会破坏CSRF防护的安全性。
内容的提问来源于stack exchange,提问作者Stefanos Kargas
相关产品推荐
相关产品推荐

