web-dev-qa-db-ja.com

angular4 httpclient csrfはx-xsrf-tokenを送信しません

angularドキュメンテーションでは、angular httpclientは自動的にcookieの値を送信しますXSRF-TOKENヘッダー内X-XSRF-TOKEN投稿リクエスト。 ドキュメントリンク

ただし、ヘッダーは送信されません。ここに私のコードがあります

Cookieを設定するNodejsコード

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

App.module.tsでhttpclientを使用しました

imports: [
  HttpClientModule
]

**上記のコードはデバッグ用です。 set-csrfエンドポイントがありません。

ただし、投稿要求を送信するときにヘッダーは送信されません。デバッグできません。

angular too。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の問題

20
netuser

探しているのはHttpClientXsrfModuleです。

詳細については、こちらをお読みください: https://angular.io/api/common/http/HttpClientXsrfModule

使用法は次のようになります。

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

さらに、コードが絶対URLを介してAPIをターゲットにしている場合、デフォルトの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 }
]
45
Miroslav Jonas

正しいメソッドはwithOptionsだと思います。 withConfigを使用して、エラー_Property 'withConfig' does not exist on type 'typeof HttpClientXsrfModule'._が発生しました。これはドキュメントのタイピングの問題です。代わりに「withOptions」を使用する必要がありますHttpClientXsrfModule.withOptions({ cookieName: 'My-Xsrf-Cookie', headerName: 'My-Xsrf-Header', })

7
Manu Chadha

最近のAngularバージョンを使用すると、次の問題に遭遇しました。 「X-XSRF-TOKEN」ですので、ここで私のために動作する上記のMiroslavのコードを少し修正したバージョンを示します。

@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);
  }
}
0
boto