在angular4 項目中,每次請求服務端需要添加頭部信息AccessToken作為認證的憑據。但如果在每次調用服務端就要寫代碼添加一個頭部信息,會變得很麻煩。可以使用angular4的HttpClient來攔截每個請求,然后在頭部添加上信息。
直接上代碼實踐
一、創建攔截器Service,實現HttpInterceptor的intercept方法
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;
}
}
二、注冊攔截器,在APPModule中,添加如下代碼
{ provide: HTTP_INTERCEPTORS, useClass: BaseHttpInterceptorService,// 上邊定義的攔截器名字 multi: true },
三、每個請求服務端數據的Service依賴HttpClient,而不是http。
那么一個基礎的攔截器已經完成了,但是,你會發現調用認證服務Service的時候,會報錯:Cyclic dependency error with HttpInterceptor ,如果添加了第一步代碼中注意點那段代碼后,又會發現OK了。
這是依賴注入循環嵌套:A依賴B,B中又引用A。
官方文檔中采用forwardRef,但是發現沒用。在Stack Overflow中看到有人采用上述方法成功解決問題。https://github.com/angular/angular/issues/18224
如需要更詳細的代碼或有問題,請聯系我
