Angular 5中xsrf-token Cookie与X-XSRF-TOKEN header值不一致求助
解决并发请求时XSRF-Token不匹配的问题
这个问题我之前也碰到过,核心原因是后端每次请求都会更新XSRF-TOKEN Cookie,但并发请求时,部分请求发起时还没拿到最新的Cookie值——毕竟浏览器要等第一个请求返回后才会更新Cookie,而你同时发起的其他请求已经用了旧的Token,自然就不匹配了。
下面给你几个可行的解决方案,按推荐优先级排序:
1. 优先和后端沟通,调整Token更新策略
其实XSRF-Token的核心作用是防止跨站请求伪造,并不需要每次请求都更新。通常只需要在用户登录、会话状态变更时更新一次就足够了。如果后端能调整这个策略,并发请求的问题会直接消失,这是最省心的办法。
2. 串行化你的并发请求
如果后端必须每次请求都更新Token,那你需要确保请求是串行执行的——也就是前一个请求完成(Cookie更新后),再发起下一个请求。这样每个请求都能拿到最新的XSRF-TOKEN值。
用RxJS的concatMap可以轻松实现:
import { from } from 'rxjs'; import { concatMap } from 'rxjs/operators'; // 把你要发送的请求整理成数组 const requestQueue = [ this.http.post<any>('/api/route1', params1), this.http.post<any>('/api/route2', params2), this.http.post<any>('/api/route3', params3) ]; // 串行执行所有请求 from(requestQueue).pipe( concatMap(req => req) ).subscribe( res => console.log('请求成功:', res), err => console.error('请求失败:', err) );
3. 自定义XSRF拦截器(适用于非并发或间隔发起的请求)
如果你不想串行请求,也可以自定义一个HTTP拦截器,确保每个请求发起前都重新读取最新的Cookie值。不过要注意:这个方法只对非同时发起的请求有效,如果还是并发发起,第一个请求更新Cookie时,其他请求已经用了旧值。
拦截器代码示例:
import { Injectable } from '@angular/core'; import { HttpInterceptor, HttpRequest, HttpHandler, HttpEvent } from '@angular/common/http'; import { Observable } from 'rxjs'; import { CookieService } from 'ngx-cookie-service'; @Injectable() export class XsrfInterceptor implements HttpInterceptor { constructor(private cookieService: CookieService) {} intercept(req: HttpRequest<any>, next: HttpHandler): Observable<HttpEvent<any>> { // 只对非GET/HEAD/OPTIONS的请求添加XSRF头(符合XSRF防护的常规场景) if (!req.method.match(/GET|HEAD|OPTIONS/)) { const latestToken = this.cookieService.get('XSRF-TOKEN'); if (latestToken) { req = req.clone({ headers: req.headers.set('X-XSRF-TOKEN', latestToken) }); } } return next.handle(req); } }
然后在你的AppModule中注册这个拦截器:
import { HTTP_INTERCEPTORS } from '@angular/common/http'; import { XsrfInterceptor } from './xsrf.interceptor'; @NgModule({ providers: [ { provide: HTTP_INTERCEPTORS, useClass: XsrfInterceptor, multi: true } ] }) export class AppModule {}
为什么你之前的手动设置无效?
你之前的代码是在请求发起前一次性获取Cookie值:
this.http.post<any>(route, params, { headers: new HttpHeaders({ 'X-XSRF-TOKEN': this.cookieService.get("XSRF-TOKEN") }) })
但并发请求时,所有请求的get("XSRF-TOKEN")都是在同一时间执行的,此时第一个请求还没返回,Cookie还没更新,所以所有请求用的都是旧Token,自然会出现不匹配的情况。
内容的提问来源于stack exchange,提问作者LokiKartik




