Angular4---認證---使用HttpClient攔截器,解決循環依賴引用的問題

  在angular4 項目中,每次請求服務端須要添加頭部信息AccessToken做爲認證的憑據。但若是在每次調用服務端就要寫代碼添加一個頭部信息,會變得很麻煩。能夠使用angular4的HttpClient來攔截每一個請求,而後在頭部添加上信息。git

  直接上代碼實踐github

  1、建立攔截器Service,實現HttpInterceptor的intercept方法api

import { Injectable, Injector} from '@angular/core';
import {HttpEvent, HttpHandler, HttpInterceptor, HttpRequest, HttpResponse} from '@angular/common/http';
import {Observable} from 'rxjs/Observable';
import 'rxjs/add/operator/do';
import {AuthenticationService} from './auth/authentication.service'; // 用於得到AccessToken的服務類
import {environment} from '../../environments/environment';

/**
 * HTTP攔截器,設置頭部信息
 */
@Injectable()
export class BaseHttpInterceptorService implements HttpInterceptor {

  authService: AuthenticationService;
  skipAuth: [string];
  constructor(private inject: Injector) {
  // 用戶登陸或認證請求則不須要添加頭部AccessToken信息
    this.skipAuth = [
      `${environment.serverUrl}/api/v1/User/login`,
    ];
  }
  /**
   * 攔截器攔截請求
   * @param {HttpRequest<any>} req
   * @param {HttpHandler} next
   * @returns {Observable<HttpEvent<any>>}
   */
  intercept(req: HttpRequest<any>, next: HttpHandler): Observable<HttpEvent<any>> {
    this.authService = this.inject.get(AuthenticationService);// 注意此句 const req_started = Date.now();
    let authReq;
    /**
     * 若是是跳過認證的連接,則不添加頭部信息
     */
    if (this.isSkipAuth(req.url)) {
      authReq = req.clone();
    }else {
      const access_token = `Bearer ${this.authService.getAccessToken('563151811@qq.com')}`;
      authReq = req.clone({
        setHeaders: {
          Authorization: access_token
        }
      });
    }
    return next.handle(authReq).do(event => {
      if (event instanceof HttpResponse) {
        const elapsed = Date.now() - req_started;
        console.log(`Request for ${req.urlWithParams} took ${elapsed} ms`);
      }
    });
  }
  /*
   *是否跳過添加頭部認證
  */
  isSkipAuth(url: string) {
    let isMatch = false;
    this.skipAuth.forEach((reg_url: string) => {
      if ( !isMatch) {
        if (url.search(reg_url) >= 0) {
          isMatch = true;
        }
      }
    });
    return isMatch;
  }
}

  2、註冊攔截器,在APPModule中,添加以下代碼angular4

{
      provide: HTTP_INTERCEPTORS,
      useClass: BaseHttpInterceptorService,// 上邊定義的攔截器名字
      multi: true
    },

  3、每一個請求服務端數據的Service依賴HttpClient,而不是http。ide

  那麼一個基礎的攔截器已經完成了,可是,你會發現調用認證服務Service的時候,會報錯:Cyclic dependency error with HttpInterceptor ,若是添加了第一步代碼中注意點那段代碼後,又會發現OK了。this

  這是依賴注入循環嵌套:A依賴B,B中又引用A。url

  官方文檔中採用forwardRef,可是發現沒用。在Stack Overflow中看到有人採用上述方法成功解決問題。https://github.com/angular/angular/issues/18224spa

如須要更詳細的代碼或有問題,請聯繫我code

相關文章
相關標籤/搜索