Angular4 httpclient csrf не отправляет x-xsrf-токен

В угловой документации упоминается, что угловой httpclient автоматически отправит значение cookie XSRF-TOKEN в шапке X-XSRF-TOKEN почтового запроса. Ссылка на документацию

Но это не отправляет заголовок для меня. Вот мой код

Код Nodejs для установки куки

router.get('/set-csrf',function(req,res,next){
    res.setHeader('Set-Cookie', "XSRF-TOKEN=abc;Path=/; HttpOnly; SameSite=Strict");    
    res.send();
  })

Я использовал httpclient в app.module.ts

imports: [
  HttpClientModule
]

** Приведенный выше код предназначен только для отладки. У меня нет конечной точки set-csrf.

Но он не отправляет заголовок при отправке запроса. Я не могу отлаживать.

Я добавил проблему в github репозиторий angular. HttpXsrfInterceptor проверяет, является ли запрос GET или HEAD или он начинается с http. Если true, пропускает добавление заголовка.

Вот код в классе HttpXsrfInterceptor

intercept(req: HttpRequest<any>, next: HttpHandler): Observable<HttpEvent<any>> {
    const lcUrl = req.url.toLowerCase();
    // Skip both non-mutating requests and absolute URLs.
    // Non-mutating requests don't require a token, and absolute URLs require special handling
    // anyway as the cookie set
    // on our origin is not the same as the token expected by another origin.
    if (req.method === 'GET' || req.method === 'HEAD' || lcUrl.startsWith('http://') ||
        lcUrl.startsWith('https://')) {
      return next.handle(req);
    }
    const token = this.tokenService.getToken();

    // Be careful not to overwrite an existing header of the same name.
    if (token !== null && !req.headers.has(this.headerName)) {
      req = req.clone({headers: req.headers.set(this.headerName, token)});
    }
    return next.handle(req);
  }

Я не уверен, почему они пропустили часть http / s. Вот моя проблема в GitHub

3 ответа

То, что вы ищете, это HttpClientXsrfModule,

Пожалуйста, прочитайте больше об этом здесь: https://angular.io/api/common/http/HttpClientXsrfModule.

Ваше использование должно быть таким:

imports: [   
 HttpClientModule,  
 HttpClientXsrfModule.withConfig({
   cookieName: 'My-Xsrf-Cookie', // this is optional
   headerName: 'My-Xsrf-Header' // this is optional
 }) 
]

Кроме того, если ваш код предназначается для API через абсолютный URL-адрес, перехватчик CSRF по умолчанию не будет работать из коробки. Вместо этого вы должны реализовать свой собственный перехватчик, который не игнорирует абсолютные маршруты.

@Injectable()
export class HttpXsrfInterceptor implements HttpInterceptor {

  constructor(private tokenExtractor: HttpXsrfTokenExtractor) {
  }

  intercept(req: HttpRequest<any>, next: HttpHandler): Observable<HttpEvent<any>> {
    const headerName = 'X-XSRF-TOKEN';
    let token = this.tokenExtractor.getToken() as string;
    if (token !== null && !req.headers.has(headerName)) {
      req = req.clone({ headers: req.headers.set(headerName, token) });
    }
    return next.handle(req);
  }
}

И наконец добавьте его своим провайдерам:

providers: [
  { provide: HTTP_INTERCEPTORS, useClass: HttpXsrfInterceptor, multi: true }
]

Я полагаю, правильный метод withOptions, Я использовал withConfig и получил ошибку Property 'withConfig' does not exist on type 'typeof HttpClientXsrfModule'. Это проблема с печатанием в документации. Вам нужно использовать "withOptions" вместо HttpClientXsrfModule.withOptions({ cookieName: 'My-Xsrf-Cookie', headerName: 'My-Xsrf-Header', })

Используя последнюю версию Angular, я столкнулся со следующей проблемой. Пока токен передается клиенту с использованием имени заголовка "XSRF-TOKEN", ответ должен возвращать токен с использованием имени заголовка "X-XSRF-TOKEN". Итак, вот слегка измененная версия кода Мирослава выше, которая работает для меня.

@Injectable()
export class HttpXSRFInterceptor implements HttpInterceptor {

  constructor(private tokenExtractor: HttpXsrfTokenExtractor) {
  }

  intercept(req: HttpRequest<any>, next: HttpHandler): Observable<HttpEvent<any>> {
    const headerName = 'XSRF-TOKEN';
    const respHeaderName = 'X-XSRF-TOKEN';
    let token = this.tokenExtractor.getToken() as string;
    if (token !== null && !req.headers.has(headerName)) {
      req = req.clone({ headers: req.headers.set(respHeaderName, token) });
    }
    return next.handle(req);
  }
}
Другие вопросы по тегам