Angular异步HTTP拦截器(HTTPInterceptor)
Angular 附带的HttpClient API 接口是该API中最有用的功能,其中最重要的功能之一HttpInterceptor(HTTP拦截器)
,它使我们能够全局地拦截和转换HTTP请求。拦截器早已在AngularJS中提供,它们对于诸如身份验证之类的东西特别有用,在身份验证中,通常需要在每个请求中包含一个auth令牌。
在之前,HttpInterceptor
我们将为Angular的内置HttpModule
应用创建一个包装服务,我们的应用程序将与之交互,而不是HttpModule
直接调用方法。一切都感觉有些麻烦。
现在,我们可以HttpClientModule
直接使用拦截器作为管道中的中间件。干净整洁。
最近的项目中用到了Http Interceptor
,但是遇到了问题。当APP发出HTTP请求时,该请求必须包含token令牌才能正确进行身份验证,但是token令牌仅可从异步获取(首次或失效时)。这意味着我需要以某种方式暂停HTTP请求,直到token令牌可用为止。
对我来说,如何实现这一目标并不是立即显而易见的,而且官方也没有有用的文档。所以我想我将其记录在这里。也许对其他人会有帮助。
注意:本教程仅侧重于创建HttpInterceptor
适合现有项目的异步。
一、增加 http interceptor
- import { Injectable } from "@angular/core";
- import {
- HttpRequest,
- HttpHandler,
- HttpEvent,
- HttpInterceptor,
- HTTP_INTERCEPTORS,
- } from "@angular/common/http";
- import { Observable } from "rxjs";
- import { map, mergeMap } from "rxjs/operators";
- import { TokenService } from "src/app/core/services/token.service";
- import { IToken } from "../model/IToken";
- const TOKEN_HEADER_KEY = "Authorization";
- //auto add token to header for http request
- @Injectable()
- export class AuthInterceptor implements HttpInterceptor {
- constructor(private tokenService: TokenService) {}
- intercept(
- request: HttpRequest<any>,
- next: HttpHandler
- ): Observable<HttpEvent<any>> {
- //skip token url
- if (request.url.indexOf("token") == -1) {
- return this.tokenService.getToken().pipe(
- mergeMap((res) => {
- console.log(res);
- let token = res as IToken;
- //sessionStorage.setItem('token', token.token);
- request = request.clone({
- headers: request.headers.set(
- TOKEN_HEADER_KEY,
- "Bearer " + token.token
- ),
- });
- return next.handle(request);
- })
- );
- } else {
- return next.handle(request);
- }
- }
- }
- export const authInterceptorProviders = [
- { provide: HTTP_INTERCEPTORS, useClass: AuthInterceptor, multi: true },
- ];
二、tokenService (从sessionStorage中获取token,当token失效时,从Http中获取)
- import{Injectable} from "@angular/core";
- import{JwtHelperService} from "@auth0/angular-jwt";
- import{HttpClient,HttpHeaders} from "@angular/common/http";
- import{ environment } from "../../../environments/environment";
- import{IToken} from "src/app/shared/model/IToken";
- import{Observable, of } from "rxjs";
- const helper =newJwtHelperService();
- @Injectable({
- providedIn:"root",
- })
- exportclassTokenService{
- constructor(private http:HttpClient){}
- //getToken
- public getToken():Observable<object>{
- let token = sessionStorage.getItem("token");
- if(!token ||!helper.isTokenExpired(token)){
- let data ={
- client_id: environment.clientId,
- client_secret: environment.clientSecret,
- grant_type:"client_credentials",
- };
- let res =this.http.post(environment.tokenUrl, data);
- return res;
- }else{
- return of({ token: token });
- }
- }
- }
三、在app.module中增加interceptor
- import { BrowserModule } from "@angular/platform-browser";
- import { NgModule } from "@angular/core";
- import { HttpClientModule, HTTP_INTERCEPTORS } from "@angular/common/http";
- import { AppRoutingModule } from "./app-routing.module";
- import { AppComponent } from "./app.component";
- import { BrowserAnimationsModule } from "@angular/platform-browser/animations";
- import { authInterceptorProviders } from "./shared/interceptor/auth.interceptor";
- @NgModule({
- declarations: [AppComponent],
- imports: [
- BrowserModule,
- AppRoutingModule,
- ChatModule,
- HttpClientModule,
- MaterialModule,
- BrowserAnimationsModule,
- ],
- providers: [authInterceptorProviders],
- bootstrap: [AppComponent],
- })
- export class AppModule {}