使用Ionic 2中的拦截器导航到获取状态401的登录页面

时间:2017-08-10 12:56:28

标签: angular http ionic2

import { Injectable } from '@angular/core';
import { Http, ConnectionBackend, Headers, RequestOptions, Request, Response, RequestOptionsArgs } from '@angular/http';
import { Observable } from 'rxjs/Observable';
import 'rxjs/add/operator/catch';
import 'rxjs/add/observable/throw';

@Injectable()
export class SecureHttpService extends Http {

  constructor(backend: ConnectionBackend, defaultOptions: RequestOptions) {
    super(backend, defaultOptions);
  }

  request(url: string | Request, options?: RequestOptionsArgs): Observable<Response> {
    // return super.request(url, options);
    return super.request(url, options).catch(this.catchErrors());
  }

   private catchErrors() {
    return (res: Response) => {
      if (res.status === 401 || res.status === 403) {
          //nav.push(loginPage); I want to do something like this if status is 401
        debugger;
      }
      return Observable.throw(res);
    };
  }

我正在尝试在401错误状态时导航到登录页面,但由于ionic不允许在服务中使用服务。如何实现这一目标?

app.module.ts: -

 providers: [
{
    provide: Http,
    useFactory: (backend:XHRBackend, defaultOptions:RequestOptions) => {
        return new SecureHttpService(backend, defaultOptions);
    },
    deps: [XHRBackend, RequestOptions]
},
StatusBar,
SplashScreen,
{provide: ErrorHandler, useClass: IonicErrorHandler}
]

2 个答案:

答案 0 :(得分:1)

app.component.ts或您的第一页中:

  import { NavController, Events } from 'ionic-angular';

  constructor(navCtrl: NavController, events: Events) {
      this.events.subscribe('http:forbidden', error => {
          this.navCtrl.push(LoginPage, {errorMessage: error});
      });
  }

现在您可以从服务中发出:

import { Injectable } from '@angular/core';
import { Http, ConnectionBackend, Headers, RequestOptions, Request, Response, RequestOptionsArgs } from '@angular/http';
import { Observable } from 'rxjs/Observable';

import { Events } from 'ionic-angular';

import 'rxjs/add/operator/catch';
import 'rxjs/add/observable/throw';

@Injectable()
export class SecureHttpService extends Http {

  constructor(public events: Events, backend: ConnectionBackend, defaultOptions: RequestOptions) {
    super(backend, defaultOptions);
  }

  request(url: string | Request, options?: RequestOptionsArgs): Observable<Response> {
    // return super.request(url, options);
    return super.request(url, options).catch(this.catchErrors());
  }

   private catchErrors() {
    return (res: Response) => {
      if (res.status === 401 || res.status === 403) {
          // will trigger the event defined earlier which did have access to the NavController
          this.events.publish('http:forbidden', "Something went wrong.");
        debugger;
      }
      return Observable.throw(res);
    };
  }

答案 1 :(得分:0)

@Ukkarsh Prakash我有同样的问题,我使用拦截器将我的oAuth令牌推送到每个http请求的auth头。然后,我想使用相同的拦截器来检测来自我的api的响应401,然后显示我的登录页面。由于我在上面没有看到任何拦截器(如在var newAsset = getFactory().newResource(org.biznet,'ourAsset',assetID); 中),让我发布我的代码:

implements HttpInterceptor

@ Ivaro18上面详述的重要部分是(在我的情况下)401上的事件的提升。然后在我的HomePage等效词中添加了以下内容:

@Injectable()
export class AuthenticationInterceptor implements HttpInterceptor {

    constructor(private tokenStorage: TokenStorage, private events: Events) {}

    intercept(request: HttpRequest<any>, next: HttpHandler): Observable<HttpEvent<any>> {
        return this.tokenStorage.getTokenObservable().mergeMap((token: Token) => {
            // add the Bearer token to the header
            if (token != null) {
                request = request.clone({
                    setHeaders: {
                        Authorization: `Bearer ${token.access_token}`
                    }
                });
            }
            return next.handle(request).do((event: HttpEvent<any>) => {
                // do something with the response if you want to
            }, (err: any) => {
                // we are interested on error
                if (err instanceof HttpErrorResponse) {
                    if (err.status === 401) {
                        this.events.publish('http:forbidden', "Session Expired");
                    }
                }
            });
        });
    }
}

然后当任何http调用返回401时,我的应用程序显示登录页面