摘要:攔截器的官方解釋為攔截機制是中的主要特性之一。使用這種攔截機制,你可以聲明一些攔截器,用它們監視和轉換從應用發送到服務器的請求。最后調用,以便這個請求流能走到下一個攔截器,并最終傳給后端處理器。
上一節介紹了好友模塊,這一節介紹和好友模塊中的控件有關的三個服務程序。
用HttpClient攔截器發送用戶認證信息在進入好友模塊之前,需要向服務器發送認證信息,在這里使用angular的HttpClient攔截器進行發送。
攔截器的官方解釋為:HTTP 攔截機制是 @angular/common/http 中的主要特性之一。 使用這種攔截機制,你可以聲明一些攔截器,用它們監視和轉換從應用發送到服務器的 HTTP 請求。 攔截器還可以用監視和轉換從服務器返回到本應用的那些響應。 多個選擇器會構成一個“請求/響應處理器”的雙向鏈表。如果想詳細了解攔截器,可以看官方文檔
我們利用攔截器在每次向服務器請求朋友列表時將認證信息加入到頭部。
具體代碼如下:
import { Injectable } from "@angular/core"; import { HttpEvent, HttpInterceptor, HttpHandler, HttpRequest } from "@angular/common/http"; import { Observable } from "rxjs/observable"; import { AuthTokenService } from "./authtoken.service"; @Injectable() export class AuthInterceptor implements HttpInterceptor{ constructor( private tokenServ: AuthTokenService ){} intercept(req: HttpRequest,next: HttpHandler) : Observable >{ //獲取認證信息 const auth = this.tokenServ.getToken(); //克隆request,加入新的頭信息 const authReq = req.clone({headers:req.headers.set("Authorization", "Bearer " + auth)}); return next.handle(authReq); } }
要實現攔截器,就要實現一個實現了 HttpInterceptor 接口中的 intercept() 方法的類(AuthInterceptor)。在intercept()方法中先通過AuthTokenService的getToken()方法取得認證信息。這些認證信息是在登錄或注冊成功后由服務器發回來的jwt認證信息。服務器如何發送這些信息請參考第三節的內容,認證信息的內容是登錄或認證的用戶ID。因為HttpRequest 實例的屬性卻是只讀(readonly)的,要修改請求信息只能先克隆它。在這里利用clone()方法在請求的頭部信息中加入認證信息( clone() 方法的哈希型參數允許你在復制出克隆體的同時改變該請求的某些特定屬性)。最后調用 next.handle(),以便這個請求流能走到下一個攔截器,并最終傳給后端處理器。
最后還需要向模塊這個攔截器,這個AuthInterceptor攔截器就是一個由 Angular 依賴注入 (DI)系統管理的服務,你必須在提供 HttpClient 的同一個(或其各級父注入器)注入器中提供這些攔截器。在好友模塊的providers中加入
{ provide: HTTP_INTERCEPTORS, useClass: AuthInterceptor, multi:true }
現在在好友模塊中每個發送到服務器的請求都會在頭部加上認證信息。
補充內容:服務器jwt認證中間件
express的jwt中間件定義代碼如下:
var expressJwt = require("express-jwt"); //使用jwt攔截 app.use(expressJwt({ secret: "secret" })); //處置jwt異常 app.use(function (err, req, res, next) { if (err.name === "UnauthorizedError") { res.status(401).send({ "code": 401, "msg": "invalid token" }); } }); app.use("/friends", friends);
一定要把處理friends訪問的路由放到jwt中間件后面,不然jwt無法進行驗證。
利用路由守衛保證未登錄用戶無法訪問好友信息在上一節介紹路由時,在路由配置中加入了canActivate: [AuthGuardService],這是angular路由守衛服務,路由守衛的作用在官方文檔中的解釋如下:
現在,任何用戶都能在任何時候導航到任何地方。 但有時候這樣是不對的。
該用戶可能無權導航到目標組件。
可能用戶得先登錄(認證)。
在顯示目標組件前,你可能得先獲取某些數據。
在離開組件前,你可能要先保存修改。
你可能要詢問用戶:你是否要放棄本次更改,而不用保存它們?
你可以往路由配置中添加守衛,來處理這些場景。
守衛返回一個值,以控制路由器的行為:
如果它返回 true,導航過程會繼續
如果它返回 false,導航過程會終止,且用戶會留在原地。
在這里我們利用路由守衛要求用戶先登錄才能導航到birthday模塊中的控件。
代碼如下:
import { Injectable } from "@angular/core"; import { CanActivate, ActivatedRouteSnapshot, RouterStateSnapshot, Router } from "@angular/router"; import { UserService } from "./user.service"; import { AuthTokenService } from "./authtoken.service"; @Injectable() export class AuthGuardService implements CanActivate { constructor( private tokenServe: AuthTokenService, private router: Router) { } canActivate(route: ActivatedRouteSnapshot, state: RouterStateSnapshot) { if (this.tokenServe.getToken() !== null) { return true; } this.router.navigate(["/login"]); return false; } }
路由守衛類也是一個注入服務類,它需要實現CanActivate接口的canActivate()方法。canActivate()方法實現了守衛代碼。代碼很簡單,從AuthTokenService類的getToken()中獲取認證信息的值,如果有就返回true,如果沒有就導航到登錄頁面。并返回false。
最后記住在birthday模塊中providers中加入AuthGuardService。
BirthdayService類為birthday模塊提供了數據服務,代碼如下:
import { Injectable } from "@angular/core"; import { HttpClient, HttpHeaders,HttpErrorResponse } from "@angular/common/http"; import { UserService } from "../user.service"; import "rxjs/add/operator/map"; export class Friend { constructor( public fid: number, public fname: string, public fbirth: Date, public fnumber: string, public femail: string, public fgroup: string, public state: string, public photo: string, public uid:number ) { } } @Injectable() export class BirthdayService { constructor( private userServ: UserService, private http: HttpClient) { } //獲取全部朋友信息 getFriends() { return this.http.get("http://localhost:3000/friends/friend-list", { observe: "response"});} //獲取單個朋友信息 getFriend(id: number | string) { return this.getFriends().map(res => { if (res.body["code"] === "200") { return res.body["results"].find(result => result.fid === +id);} }); } //修改朋友信息 editFriend(friend: Friend){ const body = {"value":friend,"operate":"edit"}; return this.http.post("http://localhost:3000/friends/editfriend",body); } //新建朋友信息 newFriend(friend: Friend){ const body = {"value":friend,"operate":"new"}; return this.http.post("http://localhost:3000/friends/editfriend", body); } //刪除好友 deleteFriend(friend:Friend){ const body = {"value":friend, "operate":"delete"}; return this.http.post("http://localhost:3000/friends/editfriend",body); } //錯誤處理 handleError(err: HttpErrorResponse): string { if (err.error instanceof Error) { return "發生錯誤,錯誤信息:" + err.error.message; } else { console.log(`Backend returned code ${err.status}, body was: ${err.error["msg"]}`); return err.error["msg"]; } } }
首先在類外定義了一個Friend類,在這個類中定義了friend信息。BirthdayService類的主要功能有6部分:
獲取全部朋友信息。通過HttpClient的get方法發送獲取到全部的friend信息的請求。
獲取單個朋友信息。getFriends()方法返回的是一個Observable對象,利用Observable的map()函數的回調找到對應id的單個friend對象,并繼續發射Observable對象。
修改朋友信息。將修改后的friend信息post到服務器。在發送的body中,除了修改后的friend對象,還發送了一個字符串屬性:"operate":"edit",用于區分是修改friend還是新建friend,這了的edit代表修改信息。(具體的服務器操作代碼將在下一章介紹)。
新建朋友信息。和修改friend信息同理,只不過將body中的"operate"改為"new"。
刪除好友。也和修改friend信息同理,只不過將body中的"operate"改為"delete"。
錯誤處理。如果是客戶端(angular代碼)出了錯,會拋出一個 Error 類型的異常,由此判斷如果錯誤的類型是Error類型,就表示前端出錯,返回一條錯誤信息:"發生錯誤,錯誤信息:" + err.error.message;。如果是后端出錯,就打印出錯誤狀態和信息。
關于birthday模塊的服務程序就介紹完了。下一章將要介紹服務器端express框架如何處理這些請求。今天將我的代碼傳到了github上,方便大家參考。地址如下:
前端:https://github.com/db991400/b...
后端:https://github.com/db991400/b...
文章版權歸作者所有,未經允許請勿轉載,若此文章存在違規行為,您可以聯系管理員刪除。
轉載請注明本文地址:http://specialneedsforspecialkids.com/yun/94572.html
摘要:后臺注冊成功后,會返回狀態的認證信息。后臺數據的處理,詳見利用和構建一個簡單的網站三訪問。在這個方法中分別針對這兩種錯誤進行處理。 上一節簡單介紹了一下利用angular構建的主路由模塊,根據上一節的介紹,主頁面加載時直接跳轉到用戶管理界面,下面就來介紹一下用戶管理模塊。啟動應用后,初始界面應該是這樣的: showImg(https://segmentfault.com/img/bV3...
摘要:后臺注冊成功后,會返回狀態的認證信息。后臺數據的處理,詳見利用和構建一個簡單的網站三訪問。在這個方法中分別針對這兩種錯誤進行處理。 上一節簡單介紹了一下利用angular構建的主路由模塊,根據上一節的介紹,主頁面加載時直接跳轉到用戶管理界面,下面就來介紹一下用戶管理模塊。啟動應用后,初始界面應該是這樣的: showImg(https://segmentfault.com/img/bV3...
摘要:上一章通過用戶注冊講解了響應式表單,這章主要講解如何向服務器提交注冊數據并導航到好友信息模塊。利用的方法將這個憑證存儲到本地。針對一個進行數據存儲。當用戶關閉瀏覽器窗口后,數據會被刪除。 上一章通過用戶注冊講解了響應式表單ReactiveForm,這章主要講解如何向服務器提交注冊數據并導航到好友信息模塊。 提交注冊信息 向服務器提交信息是通過模板中標簽中的(ngSubmit)=onSu...
閱讀 1751·2023-04-25 22:42
閱讀 2202·2021-09-22 15:16
閱讀 3485·2021-08-30 09:44
閱讀 485·2019-08-29 16:44
閱讀 3304·2019-08-29 16:20
閱讀 2512·2019-08-29 16:12
閱讀 3387·2019-08-29 16:07
閱讀 666·2019-08-29 15:08