typescript Angular 6 - 身份验证令牌拦截器不添加标头

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/51447545/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-10-21 05:32:35  来源:igfitidea点击:

Angular 6 - Auth token interceptor not adding headers

angulartypescript

提问by kriskanya

Using Angular 6, I have tried many different approaches over the last two days, with the latest riffing off of this post: https://stackoverflow.com/a/47401544. However, the header is still not being set on requests.

使用 Angular 6,我在过去两天尝试了许多不同的方法,最新的这篇文章是:https: //stackoverflow.com/a/47401544。但是,标头仍未在请求上设置。

import {Inject, Injectable} from '@angular/core';
import {
  HttpEvent,
  HttpInterceptor,
  HttpHandler,
  HttpRequest,
  HttpErrorResponse,
} from '@angular/common/http';
import { Observable } from 'rxjs/Observable';

@Injectable()
export class AuthTokenInterceptor implements HttpInterceptor {
  constructor() {}

  intercept(req: HttpRequest<any>, next: HttpHandler): Observable<HttpEvent<any>> {
    return next.handle(req).do((event: HttpEvent<any>) => {
      if (localStorage.getItem('id_token') != null) {
        // Clone the request to add the new header.
        const request = req.clone({
          setHeaders: {
            'Content-Type' : 'application/json; charset=utf-8',
            'Accept'       : 'application/json',
            'Authorization': `Bearer ${localStorage.getItem('id_token')}`
          }
        });
        return next.handle(request);
      }
    }, (err: any) => {
      if (err instanceof HttpErrorResponse) {
        if (err.status === 401) {
          console.log('redirect auth interceptor')
          // do a redirect
        }
      }
    });
  }
}

If I log out request, the request.headers.lazyUpdatearray is being updated with 3 items, but I don't see the Authorizationheader in the request it's intercepting.

如果我注销request,该request.headers.lazyUpdate数组将更新为 3 个项目,但我Authorization在它拦截的请求中看不到标头。

request.headers.lazyUpdate:

request.headers.lazyUpdate

{name: "Content-Type", value: "application/json; charset=utf-8", op: "s"}
{name: "Accept", value: "application/json", op: "s"}
{name: "Authorization", value: "Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ2Mzh9.tLTmPK46NhXSuqoCfZKgZcrQWzlNqLMI71-G0iy3bi8", op: "s"}

(request.headers.headersis empty---could this be the problem?)

request.headers.headers是空的---这可能是问题吗?)

app.module.ts:

app.module.ts:

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

What leads me to think it's an interceptor issue is that if I manually add the headers to the request, I don't get a 401and the request returns the proper data and a 200:

让我认为这是一个拦截器问题的原因是,如果我手动将标头添加到请求中,我不会得到 a401并且请求返回正确的数据和 a 200

return this.http.get(environment.API_URL + 'list/supervise/' + encodeURIComponent(id),
      {headers: new HttpHeaders().set('Authorization', `Bearer ${localStorage.getItem('id_token')}`)}).pipe(
        map((res: any) => res.data)
    );

Is there anything I may be overlooking? Thanks.

有什么我可能会忽略的吗?谢谢。

EDIT:

编辑:

As I mention in a comment below, I was returning next.handletwice. This is the solution I ended up going with:

正如我在下面的评论中提到的,我回来了next.handle两次。这是我最终采用的解决方案:

import {Injectable} from '@angular/core';
import {
  HttpEvent,
  HttpInterceptor,
  HttpHandler,
  HttpRequest
} from '@angular/common/http';
import { Observable } from 'rxjs';

@Injectable()
export class AuthTokenInterceptor implements HttpInterceptor {
  constructor() {}

  intercept(req: HttpRequest<any>, next: HttpHandler): Observable<HttpEvent<any>> {
    const token = localStorage.getItem('id_token');

    req = req.clone({
      setHeaders: {
        'Authorization': `Bearer ${token}`
      },
    });

    return next.handle(req);
  }
}

采纳答案by lupa

You could try a simpler version of it.(just like your reference link does)

你可以试试更简单的版本。( just like your reference link does)

  intercept(req: HttpRequest<any>, next: HttpHandler): Observable<HttpEvent<any>> {
    const jwt = localStorage.getItem('id_token');
    if (!!jwt) {
     req = req.clone({
       setHeaders: {
         Authorization: `Bearer ${jwt}`
       }
     });
   }
   return next.handle(req);
 }

You don't have to handle the errorhere
since the point of intercepterhere(in your context) is to clone(that means whenever we took request, we clone it, then do whatever we want and send it away).
We could add more headers more data
And it will be sent away, then eventually coming back with return from Api
And leave the handle problem to the servicethat call the httpRequest(eg: then, catch, pipe,...).

您不必处理error此处,
因为intercepter此处(在您的上下文中)的重点是克隆(这意味着无论何时我们接受请求,我们都会克隆它,然后做任何我们想做的事情并将其发送出去)。
我们可以添加更多的标题更多的数据
它会被发送出去,然后最终从 Api 返回
并将处理问题留给service调用httpRequest(例如:then, catch, pipe,...)。

Again, you declared this in app.module.tswhich mean allof the requestto api in your app will be intercept, and what if I want to handle a specific request with the error message Nothing here?, and if you do some complicated logic, it could affect all request.

And about your code above, I haven't try it, but I think their could be something wrong happened when you nested like that or so, you should put the break point their and tried to debug what happened.

同样,你宣称这app.module.ts其中的意思allrequest在您的应用程序的API将是拦截,并且如果我要处理与错误消息的具体要求Nothing here?,如果你做一些复杂的逻辑,它可能会影响所有请求。

关于您上面的代码,我还没有尝试过,但是我认为当您像这样嵌套时可能会发生错误,您应该放置断点并尝试调试发生的事情。

回答by enno.void

So the first issue i see here is that u dont return if there is no value in localStorage. i would structure the interceptor like this:

所以我在这里看到的第一个问题是,如果 localStorage 中没有值,你就不会返回。我会像这样构造拦截器:

export class AuthInterceptor implements HttpInterceptor {

    private APIToken = null;
    private defaultApplicationHeaders = {
        'Content-Type': 'application/json'
    }

    buildRequestHeaders():HttpHeaders {

        let headers = this.defaultApplicationHeaders;

        // set API-Token if available
        if(this.APIToken !== null) {
            let authHeaderTpl = `Bearer ${this.APIToken}`;
            headers['Authorization'] = authHeaderTpl
        }

        return new HttpHeaders(headers);
    }

    constructor() {
        this.APIToken = localStorage.getItem('id_token')
    }

    intercept(req: HttpRequest<any>, next: HttpHandler) {
        const headers = this.buildRequestHeaders();
        const authReq = req.clone({ headers });

        return next.handle(authReq);
    }
}

回答by kriskanya

Full solution I went with:

我使用的完整解决方案:

import {Injectable} from '@angular/core';
import {
  HttpEvent,
  HttpInterceptor,
  HttpHandler,
  HttpRequest
} from '@angular/common/http';
import { Observable } from 'rxjs';

@Injectable()
export class AuthTokenInterceptor implements HttpInterceptor {
  constructor() {}

  intercept(req: HttpRequest<any>, next: HttpHandler): Observable<HttpEvent<any>> {
    const token = localStorage.getItem('id_token');

    req = req.clone({
      setHeaders: {
        'Authorization': `Bearer ${token}`
      },
    });

    return next.handle(req);
  }
}