Angular HTTP Interceptor 的幾種使用場(chǎng)景之中,最常見的就是為 outbound HTTP 請(qǐng)求,添加 Authorization 頭部字段。
下面這段示例應(yīng)用程序有一個(gè) AuthService,它產(chǎn)生一個(gè) Authorization token
。在AuthInterceptor 中注入該服務(wù)以獲取 token,并向每個(gè)傳出請(qǐng)求添加帶有該 token 的 Authorization header:
import { AuthService } from '../auth.service'; @Injectable() export class AuthInterceptor implements HttpInterceptor { constructor(private auth: AuthService) {} intercept(req: HttpRequest<any>, next: HttpHandler) { // Get the auth token from the service. const authToken = this.auth.getAuthorizationToken(); // Clone the request and replace the original headers with // cloned headers, updated with the authorization. const authReq = req.clone({ headers: req.headers.set('Authorization', authToken) }); // send cloned request with header to the next handler. return next.handle(authReq); } }
當(dāng)然,上面先 clone 請(qǐng)求,再設(shè)置字段,有更簡(jiǎn)潔的寫法:
// Clone the request and set the new header in one step. const authReq = req.clone({ setHeaders: { Authorization: authToken } });
在 SAP Spartacus 的 Angular 代碼中也采取了上述的思路來實(shí)現(xiàn)。
一個(gè)例子:AuthHttpHeaderService
這個(gè)類是 AuthInterceptor 的一個(gè) service 類:
我們查看 alterRequest
方法的注釋,得知其作用就是給 OCC API 調(diào)用的 HTTP 請(qǐng)求添加 Authorization
字段。
首先調(diào)用第 147 行的方法 getAuthorizationHeader
,判斷當(dāng)前的請(qǐng)求對(duì)象 request:
這個(gè)方法的實(shí)現(xiàn)源代碼:
protected getAuthorizationHeader(request: HttpRequest<any>): string | null { const rawValue = request.headers.get('Authorization'); return rawValue; }
因?yàn)槿绻?qǐng)求頭部已經(jīng)擁有 Authorization
字段,我們就不應(yīng)該繼續(xù)添加了。
isOccUrl 的實(shí)現(xiàn)代碼:
protected isOccUrl(url: string): boolean { return url.includes(this.occEndpoints.getBaseUrl()); }
如果該請(qǐng)求 url 包含 OCC endpoint,并且還沒有 Authorization 字段添加,則進(jìn)入代碼第 150 行,添加 Access Token.
方法 createAuthorizationHeader
接收的參數(shù) token 的類型為 AuthToken,這是一個(gè) interface:
interface 的字段列表:
export interface AuthToken { /** * Token used for `Authorization` header. */ access_token: string; /** * Token to refresh the `access_token` when it expires. */ refresh_token?: string; /** * Time when `access_token` expires. */ expires_at?: string; /** * Scopes granted by the OAuth server. */ granted_scopes?: string[]; /** * Time when `access_token` was fetched from OAuth server and saved. */ access_token_stored_at: string; /** * Type of the `access_token`. Most often `Bearer`. */ token_type?: string; }
可見 AuthToken 接口除了包含 Access Token 之外,還有其超時(shí)時(shí)間,以及 refresh token 的值。但對(duì)于我們當(dāng)前的場(chǎng)景,我們僅需要關(guān)注 access_token
字段。
如下圖三個(gè)關(guān)鍵點(diǎn)所示:
首先檢查 token 輸入?yún)?shù)的字段 access_token
,如果可用,直接返回該字段值;
如果 access_token 字段不可用,從 Ngrx 這個(gè) memory store 里讀取出來,賦給臨時(shí)變量 currentToken
將 currentToken 的值返回給調(diào)用者
聯(lián)系客服