You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在IONIC 3的Http Interceptor中使用NavControl并实现401跳转登录

在Ionic 3中实现Http拦截器处理401跳转登录并使用NavController

为什么不能直接在拦截器中注入NavController?

因为Ionic 3基于Angular 4,拦截器属于HTTP模块的注入上下文,而NavController依赖于页面层级的注入器,直接注入会触发循环依赖错误。我们需要通过间接方式获取导航实例,或者使用事件总线解耦。


方法一:通过Ionic App服务获取NavController实例

这是最直接的方式,利用App服务获取根导航控制器来实现页面跳转。

步骤1:切换到HttpClientModule

Angular 4的拦截器仅支持HttpClient,因此需要在app.module.ts中替换原有的HttpModule:

import { HttpClientModule, HTTP_INTERCEPTORS } from '@angular/common/http';

@NgModule({
  imports: [
    // ...其他模块
    HttpClientModule // 替换 HttpModule
  ],
  providers: [
    {
      provide: HTTP_INTERCEPTORS,
      useClass: AuthInterceptor,
      multi: true // 允许多个拦截器
    }
  ]
})
export class AppModule {}

步骤2:创建Auth拦截器

新建auth.interceptor.ts,实现HttpInterceptor接口,通过App服务获取导航实例:

import { Injectable } from '@angular/core';
import { HttpInterceptor, HttpRequest, HttpHandler, HttpErrorResponse } from '@angular/common/http';
import { Observable } from 'rxjs/Observable';
import { App } from 'ionic-angular';
import { LoginPage } from '../pages/login/login'; // 导入你的登录页

@Injectable()
export class AuthInterceptor implements HttpInterceptor {

  constructor(private app: App) {}

  intercept(request: HttpRequest<any>, next: HttpHandler): Observable<any> {
    // 给请求添加Authorization头(如果有token的话)
    const authReq = request.clone({
      setHeaders: {
        Authorization: `Bearer ${localStorage.getItem('auth_token')}`
      }
    });

    // 处理响应和错误
    return next.handle(authReq).catch((error: HttpErrorResponse) => {
      if (error.status === 401) {
        // 清除本地无效token
        localStorage.removeItem('auth_token');
        // 获取根导航控制器并跳转登录页
        const rootNav = this.app.getRootNav();
        rootNav.setRoot(LoginPage);
      }
      return Observable.throw(error);
    });
  }
}

方法二:使用Ionic Events事件总线解耦

这种方式将导航逻辑从拦截器中分离,避免直接依赖导航服务,解耦性更好。

步骤1:在拦截器中触发401事件

修改拦截器,注入Events服务并发布事件:

import { Injectable } from '@angular/core';
import { HttpInterceptor, HttpRequest, HttpHandler, HttpErrorResponse } from '@angular/common/http';
import { Observable } from 'rxjs/Observable';
import { Events } from 'ionic-angular';

@Injectable()
export class AuthInterceptor implements HttpInterceptor {

  constructor(private events: Events) {}

  intercept(request: HttpRequest<any>, next: HttpHandler): Observable<any> {
    const authReq = request.clone({
      setHeaders: {
        Authorization: `Bearer ${localStorage.getItem('auth_token')}`
      }
    });

    return next.handle(authReq).catch((error: HttpErrorResponse) => {
      if (error.status === 401) {
        localStorage.removeItem('auth_token');
        // 发布401未授权事件
        this.events.publish('auth:unauthorized');
      }
      return Observable.throw(error);
    });
  }
}

步骤2:在AppComponent中监听事件并跳转

在app.component.ts中监听事件,调用NavController跳转登录页:

import { Component } from '@angular/core';
import { Platform, Events, NavController } from 'ionic-angular';
import { LoginPage } from '../pages/login/login';
import { HomePage } from '../pages/home/home';

@Component({
  templateUrl: 'app.html'
})
export class MyApp {
  rootPage: any = localStorage.getItem('auth_token') ? HomePage : LoginPage;

  constructor(
    platform: Platform,
    private events: Events,
    private navCtrl: NavController
  ) {
    platform.ready().then(() => {
      // 监听未授权事件
      this.events.subscribe('auth:unauthorized', () => {
        this.navCtrl.setRoot(LoginPage);
      });
    });
  }
}

注意事项

  • 确保登录页已经在app.module.ts的entryComponents中声明,否则Ionic无法加载该页面。
  • 使用setRoot而非push跳转登录页,避免用户通过返回按钮回到之前的未授权页面。
  • 如果你的项目仍然使用旧的Http模块而非HttpClient,需要自定义拦截器(继承Http类),但推荐升级到HttpClient以利用官方的拦截器特性。

内容的提问来源于stack exchange,提问作者user5035258

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.22 07:38:01