You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多
文档控制台
免费开始使用

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

火山引擎 最新活动