應用angular4和nodejs-express構建簡樸網站(十一)—HttpClient攔截器和路由守御

上一節引見了摯友模塊,這一節引見和摯友模塊中的控件有關的三個效勞順序。

用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<any>,next: HttpHandler) : Observable<HttpEvent<any>>{
        //獵取認證信息
         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。

birthday.service數據供應效勞引見

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…

    原文作者:黃先生
    原文地址: https://segmentfault.com/a/1190000014564176
    本文转自网络文章,转载此文章仅为分享知识,如有侵权,请联系博主进行删除。
点赞