首页 > 解决方案 > Angular HTTP 拦截器自定义预检

问题描述

我正在编写一个与后端 API 通信的应用程序,该 API 需要XSRF-TOKEN在每个请求上设置一个标头。我已经通过以下 HTTP 拦截器实现了这一点:

intercept(request: HttpRequest<unknown>, next: HttpHandler): Observable<HttpEvent<unknown>> {
  const modifiedReq = request.clone({
    headers: request.headers.set('X-XSRF-TOKEN', this.cookieService.get('XSRF-TOKEN')),
  });

  return next.handle(modifiedReq);
}

现在我需要处理XSRF-TOKEN尚未设置 cookie 的情况。在这种情况下,我需要预检我发送的请求,该请求会/csrf到达后端 API 上的特定端点,这将返回一个Set-Cookie标头 set XSRF-TOKEN

作为一个快速而肮脏的测试(没有重构以删除重复的代码),我尝试了这个:

intercept(request: HttpRequest<unknown>, next: HttpHandler): Observable<HttpEvent<unknown>> {
  if (!this.cookieService.check('XSRF-TOKEN')) {
    this.apiService.csrf().subscribe(() => {
      const modifiedReq = request.clone({
        headers: request.headers.set('X-XSRF-TOKEN', this.cookieService.get('XSRF-TOKEN')),
      });

      return next.handle(modifiedReq);
    });
  }

  const modifiedReq = request.clone({
    headers: request.headers.set('X-XSRF-TOKEN', this.cookieService.get('XSRF-TOKEN')),
  });

  return next.handle(modifiedReq);
}

但这显然会导致对/csrf端点的请求无限循环,因为拦截器内的每个 HTTP 请求都会被自己拦截......

我怎样才能实现我在这里的目标?

标签: angularhttpcsrfinterceptorpreflight

解决方案


只需让请求/csrf完成而不拦截它:

intercept(request: HttpRequest<unknown>, next: HttpHandler): Observable<HttpEvent<unknown>> {

  if (request.url === '/csrf') {
    return next.handle(request);
  }

  if (!this.cookieService.check('XSRF-TOKEN')) {
    this.apiService.csrf().subscribe(() => {
      const modifiedReq = request.clone({
        headers: request.headers.set('X-XSRF-TOKEN', this.cookieService.get('XSRF-TOKEN')),
      });

      return next.handle(modifiedReq);
    });
  }

  const modifiedReq = request.clone({
    headers: request.headers.set('X-XSRF-TOKEN', this.cookieService.get('XSRF-TOKEN')),
  });

  return next.handle(modifiedReq);
}

推荐阅读