首页 文章

angular4 httpclient csrf不发送x-xsrf-token

提问于
浏览
15

在角度文档中,提到angular httpclient 将自动在post请求的 Headers X-XSRF-TOKEN 中发送cookie XSRF-TOKEN 的值 . Documentation link

但它并没有为我发送 Headers . 这是我的代码

Nodejs code to set the cookie

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 endpoints .

但是当我发送帖子请求时它不会发送任何 Headers . 我无法调试 .

我已经在角度的github存储库中添加了该问题 . HttpXsrfInterceptor检查请求是GET还是HEAD,或者是否以http开头 . 如果为true,则跳过添加 Headers .

这是HttpXsrfInterceptor class中的代码

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部分 . 这是我的issue in github

3 回答

  • 28

    你在找什么是 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
     }) 
    ]
    

    此外,如果您的代码通过绝对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 }
    ]
    
  • 5

    我想正确的方法是 withOptions . 我使用withConfig并收到错误 Property 'withConfig' does not exist on type 'typeof HttpClientXsrfModule'. 这是文档中的输入问题 . 您需要使用"withOptions"而不是 HttpClientXsrfModule.withOptions({ cookieName: 'My-Xsrf-Cookie', headerName: 'My-Xsrf-Header', })

  • 0

    使用最近的Angular版本我遇到了以下问题 . 使用 Headers 名称“XSRF-TOKEN”将令牌传递给客户端时,响应必须使用 Headers 名称“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);
      }
    }
    

相关问题