ionic3模拟token,实现登录拦截

1、在http服务里面管理token相关信息
    注意:要在每个请求中添加token信息(和后台)
public post(url: string, params: any = null, successCallback, errorCallback): any {
  // 此处使用的post模式为非严格模式,如果要使用严格模式,请把参数放在第二个位置 覆盖null
  return this.http.post(url, null, {
    params: params,
    headers: this.getHeaders(), // 添加token信息
  }).subscribe((res: any) => {
    this.responseSuccess(res, function (msg) {
      if (successCallback) {
        successCallback(res, msg);
      }
    });
  }, err => {
    if (errorCallback) {
      errorCallback(err);
    }
  });
}
// get数据
public get(url: string, params?: any): any {
  const token = this.getToken();
  return this.http.get(url, {
    headers: this.getHeaders(), // 添加token信息
    params: params
  });
}
// 删除相关请求
public delete(url: string, params?: any): any {
  return this.http.delete(url, {
    headers: this.getHeaders(), // 添加token信息
    params: params
  });
}

完整代码:

import { Injectable } from '@angular/core';
import { HttpClient } from '@angular/common/http';
import { HttpHeaders } from '@angular/common/http';
/*
  Generated class for the HttpSerProvider provider.

  See https://angular.io/guide/dependency-injection for more info on providers
  and Angular DI.
*/
@Injectable()
export class HttpSerProvider {

  constructor(public http: HttpClient) {
    console.log('Hello HttpSerProvider Provider');
  }
  public post(url: string, params: any = null, successCallback, errorCallback): any {
    // 此处使用的post模式为非严格模式,如果要使用严格模式,请把参数放在第二个位置 覆盖null
    return this.http.post(url, null, {
      params: params,
      headers: this.getHeaders(), // 添加token信息
    }).subscribe((res: any) => {
      this.responseSuccess(res, function (msg) {
        if (successCallback) {
          successCallback(res, msg);
        }
      });
    }, err => {
      if (errorCallback) {
        errorCallback(err);
      }
    });
  }
  // get数据
  public get(url: string, params?: any): any {
    const token = this.getToken();
    return this.http.get(url, {
      headers: this.getHeaders(), // 添加token信息
      params: params
    });
  }
  // 删除相关请求
  public delete(url: string, params?: any): any {
    return this.http.delete(url, {
      headers: this.getHeaders(), // 添加token信息
      params: params
    });
  }

  /**
   * 头部信息获取,主要用于处理token
   */
  private getHeaders() {
    const token = this.getToken();
    console.log(token)
    return token ? new HttpHeaders({'token': token}) : null;
  }
  /**
   * 处理响应的事件
   * @param res
   * @param {Function} error
   */
  private responseSuccess(res: any, callback) {
    if (res.code !== '0') { // 失败
      if (res.msg) {
        callback({code: res.code, msg: res.msg});
      } else {
        const data = res.data;
        let errorMsg = '操作失败!';
        data.map(i => {
          errorMsg = i.errorMsg + '\n';
        });
        callback({code: res.code, msg: errorMsg});
      }
    } else {
      callback(res);
    }
  }

  /**
   * 处理请求失败事件
   * @param url
   * @param err
   */
  private requestFailed(url: string, err) {
    let msg = '请求发生异常';
    const status = err.status;
    if (status === 0) {
      msg = '请求失败,请求响应出错';
    } else if (status === 404) {
      msg = '请求失败,未找到请求地址';
    } else if (status === 500) {
      msg = '请求失败,服务器出错,请稍后再试';
    } else {
      msg = '未知错误,请检查网络';
    }
    return msg;

  }

  /**
   * 使用本地缓存的方式来获取token信息
   */
  getToken() {
    return window.localStorage.getItem('app-video-ai-token');
  }

  /**
   * 将token信息保存到本地缓存中 用缓存的形式实现token验证
   * @param token
   */
  setToken(token) {
    // 目前只解析token字段,缓存先只存该字段
    //  + token.name + token.email + token.avatar + token.id + token.time
    // JSON.stringify(token)
    window.localStorage.setItem('app-video-ai-token',
      token.token);
  }

  /**
   * 清理token
   */
  clearToken() {
    window.localStorage.setItem('app-video-ai-token', null);
  }
  // 监听初次加载事件入口
  load() {
    if (this.getToken()) {
    //  验证token信息,验证通过继续处于登录状态
    } else {
      // 正常去登录页面

    }
  }
}
2、编写http拦截器服务(参考ng-alain)

   1)在app.component.ts修改默认界面为首页

import { Component, ViewChild } from '@angular/core';
import { Platform } from 'ionic-angular';
import { StatusBar } from '@ionic-native/status-bar';
import { SplashScreen } from '@ionic-native/splash-screen';

import { ContentPage } from '../pages/content/content';

@Component({
  templateUrl: 'app.html'
})
export class MyApp {

  rootPage: any = ContentPage; // 默认模块

  constructor(public platform: Platform, public statusBar: StatusBar, public splashScreen: SplashScreen) {
    this.initializeApp();
  }

  initializeApp() {
    this.platform.ready().then(() => {
      // Okay, so the platform is ready and our plugins are available.
      // Here you can do any higher level native things you might need.
      this.statusBar.styleDefault();
      this.splashScreen.hide();
    });
  }

}

    2)http拦截器相关

import { Injectable, Injector } from '@angular/core';
import {
  HttpInterceptor,
  HttpRequest,
  HttpHandler,
  HttpErrorResponse,
  HttpSentEvent,
  HttpHeaderResponse,
  HttpProgressEvent,
  HttpResponse,
  HttpUserEvent,
} from '@angular/common/http';
import { Observable } from 'rxjs/Observable';
import { of } from 'rxjs/observable/of';

import { mergeMap, catchError } from 'rxjs/operators';
import { ToastController } from 'ionic-angular';
import { NavController, AlertController, App } from 'ionic-angular';
import { LoginPage } from '../../pages/login/login';
/**
 * 默认HTTP拦截器,其注册细节见 `app.module.ts`
 */
@Injectable()
export class DefaultInterceptor implements HttpInterceptor {
  constructor(private injector: Injector,
              public appCtrl : App,
              private toastCtrl: ToastController) {}

  alertMsg(message: string) {
    const toast = this.toastCtrl.create({
      message: message,
      cssClass: 'toast-message', // 目前没用 添加的位置不是想要的
      position: 'top', // “top”,“middle”,“bottom”。
      duration: 3000
    });
    toast.present();
  }

  private goTo() {
    // 退出到登录页面
    this.getNavCtrl();
    setTimeout(() => this.navCtrl.push(LoginPage));
  }
  navCtrl: NavController;
  private getNavCtrl() {
    this.navCtrl = this.appCtrl.getActiveNav();
  }
  private handleData(
    event: HttpResponse<any> | HttpErrorResponse,
  ): Observable<any> {
    // 业务处理:一些通用操作
    switch (event.status) {
      case 200:
        break;
      case 400: // Bad Request
        this.alertMsg(event['error'].msg);
        this.goTo();
        break;
      case 401: // 未登录状态码
        this.goTo();
        break;
      case 403:
      case 404:
      case 500:
        if (event['error'].msg) {
          this.alertMsg(event['error'].msg);
        }
        // this.goTo(`/${event.status}`);
        break;
      default:
        if (event instanceof HttpErrorResponse) {
          console.warn(
            '未可知错误,大部分是由于后端不支持CORS或无效配置引起',
            event,
          );
          this.alertMsg(event.message);
          this.goTo();
        }
        break;
    }
    return of(event);
  }

  intercept(
    req: HttpRequest<any>,
    next: HttpHandler,
  ): Observable<
    | HttpSentEvent
    | HttpHeaderResponse
    | HttpProgressEvent
    | HttpResponse<any>
    | HttpUserEvent<any>
  > {
    // 统一加上服务端前缀
    const url = req.url;
    // if (!url.startsWith('https://') && !url.startsWith('http://')) {
    //   url = `./` + url;
    // }

    const newReq = req.clone({
      url: url,
    });
    return next.handle(newReq).pipe(
      mergeMap((event: any) => {
        // 允许统一对请求错误处理,这是因为一个请求若是业务上错误的情况下其HTTP请求的状态是200的情况下需要
        if (event instanceof HttpResponse && event.status === 200)
          return this.handleData(event);
        // 若一切都正常,则后续操作
        return of(event);
      }),
      catchError((err: HttpErrorResponse) => this.handleData(err)),
    );
  }
}

    注意:直接在constructor中配置NavController会报错

    解决办法:

navCtrl: NavController;
  private getNavCtrl() {
    this.navCtrl = this.appCtrl.getActiveNav();
  }

    3)在app.moduel中处理拦截器相关

import { BrowserModule } from '@angular/platform-browser';
import { ErrorHandler, NgModule } from '@angular/core';
import { IonicApp, IonicErrorHandler, IonicModule } from 'ionic-angular';


import { MyApp } from './app.component';
import { ContentPage } from '../pages/content/content';
import { HomePage } from '../pages/home/home';
import { EventInfoModal } from '../pages/home/eventInfoModal';
import { LoginPage } from '../pages/login/login';
import { ListPage } from '../pages/list/list';

import { StatusBar } from '@ionic-native/status-bar';
import { SplashScreen } from '@ionic-native/splash-screen';
import { NgChartModule } from 'chartjs-ng2';
import {VgCoreModule} from 'videogular2/core';
import {VgControlsModule} from 'videogular2/controls';
import {VgOverlayPlayModule} from 'videogular2/overlay-play';
import {VgBufferingModule} from 'videogular2/buffering';
// http 服务请求
import { HttpClientModule, HTTP_INTERCEPTORS } from '@angular/common/http';
import { HttpSerProvider } from '../providers/http-ser/http-ser';
import { DefaultInterceptor } from '../providers/net/default.interceptor';

export function StartupServiceFactory(
  startupService: HttpSerProvider,
): Function {
  return () => startupService.load();
}

@NgModule({
  declarations: [
    MyApp,
    HomePage,
    EventInfoModal,
    LoginPage,
    ContentPage,
    ListPage
  ],
  imports: [
    BrowserModule,
    VgCoreModule,
    VgControlsModule,
    VgOverlayPlayModule,
    VgBufferingModule,
    IonicModule.forRoot(MyApp),
    NgChartModule,
    HttpClientModule,
  ],
  bootstrap: [IonicApp],
  entryComponents: [
    MyApp,
    HomePage,
    EventInfoModal,
    LoginPage,
    ContentPage,
    ListPage
  ],
  providers: [
    StatusBar,
    SplashScreen,
    {
      provide: ErrorHandler,
      useFactory: StartupServiceFactory,
      useClass: IonicErrorHandler
    },
    { provide: HTTP_INTERCEPTORS, useClass: DefaultInterceptor, multi: true },
    HttpSerProvider,
    HttpClientModule,
  ]
})
export class AppModule {}
3、在登录、退出登录处理相关逻辑

    1)登录模块处理登录成功后设置token

me.http.post('/upms/login',userinfo, function(res, msg){
        if (res.code === '0') {
          me.http.setToken({
            token: res.token,
            name: username.value,
            email: res.user.email,
            avatar: res.user.avatar,
            id: res.user.userId,
            time: +new Date()
          });
          me.navCtrl.push(ContentPage, userinfo);
        } else {
          me.alertMsg(res.msg);
        }
      }, function(msg){
        me.alertMsg(msg);
      });

    2)退出登录处理清理缓存,并跳转到登录页面

/**
   * 退出登录
   */
  logOut() {
    this.http.clearToken();
    this.navCrt.push(LoginPage);
    // let modal = this.modalCtrl.create(LoginPage);
    // modal.present();
  }

    

猜你喜欢

转载自blog.csdn.net/ligaoming_123/article/details/80914202
今日推荐