Ionic3的http請求如何實現token驗證,並且超時返回登錄頁


要求

  后台提供的接口,不能讓人隨便輸入個鏈接就能訪問,而是要加入一個token,token是動態的,每次訪問的時候判斷,有權限並且未過期的時候才可以訪問接口。

后台的設計是

  在登錄的時候,首先要post提交一個請求,根據用戶名密碼,返回一個動態token,這個token會在服務器保存一段時間。在前端的其他接口請求的時候,都要在header中添加這個token,后台會進行驗證。只有驗證成功,才會返回對應的接口內容,否則會拋出401異常。

請求效果

  首先使用postman查看正常請求的效果
  第一次登錄請求時,添加了Header和Body以后,返回一個動態token,其結果如下:

  服務器中保存了這個token值,然后再請求其他的get請求時,需要在Header中拼接這個token,才可以正常返回

 

添加token驗證

  Ionic的使用的是httpclient 實現的請求,所有的請求被我寫到了一個公共的http-api.service.ts 里面去了
  方法如下:

public access_token: string = '';
get<T>(endpoint: string, params?: any) {
  const headers = {
    headers: {
      'Authorization': this.access_token
    }
  };
  if (params) {
    if (!options) {
      options = {'params': params};
    } else {
      options['params'] = params;
    }
  }
  return this.http.get<T>(this.url + '/' + endpoint, headers);
}

 

  在登錄的時候,先進行token驗證,並且將返回的驗證碼信息保存在http-api.service.ts 中

public firstPost(username: string, password: string) {
  const headers = {
    headers: {
      'Authorization': 'Basic Y2xpZW50OnNlY3JldA==',
      'Content-Type': 'application/x-www-form-urlencoded'
    }
  };

  /*先token驗證,雖然是post請求,但是發現直接將參數寫到params 里面報錯,所以就直接寫到了url里面去了*/
  this.httpApi.post('oauth/token?grant_type=password&username=' + username + '&password=' + password, null
    , headers).subscribe(val => {
//返回值里,access_token代表生成的token驗證碼
      if (val != null && val['access_token'] != null) {
        this.httpApi.access_token = 'Bearer ' + val['access_token'];
      }
    }, response => {
  let toast = this.toastCtrl.create({
       message: '賬號或密碼錯誤',
       duration: 2000,
       position: 'bottom'
       });
      toast.present(toast);
    },
    () => {
    });
}

 備注:這樣做的有一個缺點。因為把token值保存在service中,service是單例的,當service刷新的時候,這個token值就不存在了。而在angular中,網上說,刷新頁面,就會刷新service。所以每次刷新頁面,必須重新登錄生成新的token 值,否則就會報401錯誤。為了解決這個問題,只有想辦法把token值 保存在一個能夠永遠取到的地方了,比如 window.localStorage ,事實上這也是比較好的一個辦法。

window.localStorage.setItem('access_token', 'Bearer ' + val['access_token']);

 

實現token超時,返回登錄頁面功能

1、添加自定義攔截器custom.error.handler.ts,如果返回401錯誤,這調用一個監聽器方法,返回登錄頁(注意:a.這里Ionic 和 Angular是不一樣的;b.沒有@Injectable(),就沒法使用構造函數)

import {ErrorHandler, Injectable} from "@angular/core";
import {Events} from "ionic-angular";

@Injectable()
export class MyErrorHandler implements ErrorHandler {

  constructor(private events: Events) {
  }

  handleError(err: any): void {
    if (err.status === 401) {
      this.events.publish('userCheck');
    }
    // do something with the errorswitch (res.status) {
  }
}

 

2、在app.module.ts 中添加引入

import {MyErrorHandler} from "./service/custom.error.handler";
...
  providers: [
    {provide: ErrorHandler, useClass: MyErrorHandler}
  ]
...

 

3、在一個Service 中添加一個全局變量,保證token超時只執行一次返回登錄頁方法

@Injectable()
export class CommonService {
  /**
   * 全局變量,保證userCheck 監聽器方法,只執行一次
   * @type {boolean} true可以執行, false不可以執行
   */
  public userCheckNum: boolean = true;
...

 

4、在tabs.ts文件中添加監聽器

ionViewDidLoad() {
  this.userCheckListenEvents();
}

ionViewWillUnload() {
  this.events.unsubscribe('userCheck');
}

userCheckListenEvents() {
  this.events.subscribe('userCheck', () => {
    if(this.commonService.userCheckNum){
      this.commonService.userCheckNum = false;
      let loader = this.loadingCtrl.create({
        content: "鏈接超時,正在返回登錄頁",
        duration: 3000
      });
      loader.present();
      loader.onDidDismiss(() => {
        this.commonService.userCheckNum = true;
        this.nav.setRoot(LoginPage);
      });

    }
  });
}

 

附錄

  后台使用的是cuba platform 框架,cuba中關於token的設計是直接集成在登錄功能里面的,在web-app.properties 配置文件里面可以進行配置
  如果添加 cuba.rest.anonymousEnabled = true ,那么任何人都可以訪問了,就沒有token驗證
  如果有token驗證,可以添加下面的配置,設置過期時間,單位是秒
    cuba.rest.client.tokenExpirationTimeSec=60
  具體參考官網文檔:https://doc.cuba-platform.com/manual-6.8/rest_api_v2_ex_get_token.html

 

原創文章,歡迎轉載,轉載請注明出處!


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM