Angular 有时无法添加 XSRF 令牌,因此我们添加了拦截器做双重检查并在丢失时添加令牌。然后我们发现它有时无法读取 cookie,所以我们添加了 3rd 方库来读取 cookie.. 但是我们仍然面临第一次尝试时缺少 XSRF 令牌的 prod 错误,特别是当从另一个站点重定向到我们这边时,随后刷新页面工作正常。
我们的一个理论是 cookie 尚未设置,即在实际设置 cookie 之前运行 cookie 的角度读取的竞争条件。认为遇到此错误的流量很低,我们需要解决这些错误并减少客户的挫败感。
现在我们想将请求保持几毫秒然后读取 cookie,即使没有找到 cookie,我们也想执行第二次 /ws/bootstrap 调用。
我很难理解或想出这个拦截器中的代码。非常感谢任何建议或参考。
同时,我将尝试在评论中发布我修改后的代码,但到目前为止,这几乎是无效的代码。
import { HttpEvent, HttpHandler, HttpInterceptor, HttpRequest, HttpXsrfTokenExtractor } from '@angular/common/http';
import { Injectable } from '@angular/core';
import { ILoggerInstance, LoggerService } from '@foo/logger-angular';
import { CookieService } from 'ngx-cookie-service';
import { Observable } from 'rxjs';
// Angular adds XSRF header only for Post, below code adds for all GET (i.e. any halHttp call)
// https://github.com/angular/angular/issues/20511
@Injectable()
export class HttpXsrfInterceptor implements HttpInterceptor {
private readonly log: ILoggerInstance;
private readonly xsrfHeaderName = 'X-XSRF-TOKEN';
private readonly xsrfCookieName = 'XSRF-TOKEN';
constructor(
private readonly tokenExtractor: HttpXsrfTokenExtractor,
private readonly cookieService: CookieService,
private readonly logger: LoggerService
) {
this.log = this.logger.getInstance('HttpXsrfInterceptor');
}
intercept(req: HttpRequest<any>, next: HttpHandler): Observable<HttpEvent<any>> {
if (!req.headers.has(this.xsrfHeaderName)) {
// We have seen header missing in prod for approx 10% traffic, so adding non angular way of retrieving cookie if angular failed for some reason.
const token = this.tokenExtractor.getToken() || this.cookieService.get(this.xsrfCookieName);
if (token) {
req = req.clone({ headers: req.headers.set(this.xsrfHeaderName, token) });
} else if (req.url !== 'ws/bootstrap' && req.url !== 'bootstrap') {
// Exclude bootstrap it issues xsrf cookie
this.log.error('Missing xsrf cookie');
}
}
return next.handle(req);
}
}