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}
]
在您的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);
};
}
@Utkarsh普拉卡什 我遇到了同样的问题,我正在使用拦截器将我的 oAuth 令牌推送到每个 http 请求的身份验证标头中。 然后,我想使用相同的拦截器来检测来自我的 api 的 401 响应,然后显示我的登录页面。 由于我在上面没有看到任何拦截器(如implements HttpInterceptor
(,让我发布我的代码:
@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");
}
}
});
});
}
}
@Ivaro18上面详述的这里的重要部分是在(在我的情况下(401 上引发事件。 然后,我在主页等效项中添加了以下内容:
constructor(events: Events, navigation: NavController) {
// watch for unauth
events.subscribe('http:forbidden', error => {
navigation.push(LoginPage, {errorMessage: error});
});
}
然后,当任何 HTTP 调用返回 401 时,我的应用程序将显示登录页面