[英]catch error while refresh token interceptor ionic
I'm using ionic 3, angular 5 and rxjs 5. I make intercepter in my app and works well with intercept all outgoing API and with add a token to the header and refresh token when the original token expired. 我使用的是ionic 3,angular 5和rxjs5。我在应用中制作了拦截器,可以很好地拦截所有传出的API,并在标头中添加令牌,并在原始令牌过期时刷新令牌。
import {Observable, BehaviorSubject} from 'rxjs';
import {_throw} from "rxjs/observable/throw";
import {take, filter, catchError, switchMap, finalize} from 'rxjs/operators';
import {Injectable, Injector} from "@angular/core";
import {HttpInterceptor, HttpRequest, HttpHandler, HttpSentEvent, HttpHeaderResponse, HttpProgressEvent,
HttpResponse, HttpUserEvent, HttpErrorResponse} from "@angular/common/http";
import {ResetApiProvider} from "../providers/reset-api/reset-api";
import {Events} from "ionic-angular";
@Injectable()
export class AuthInterceptor implements HttpInterceptor {
isRefreshingToken: boolean = false;
tokenSubject: BehaviorSubject<string> = new BehaviorSubject<string>(null);
constructor(private injector: Injector, public event: Events) {}
addToken(req: HttpRequest<any>, token: string): HttpRequest<any> {
return req.clone({setHeaders: {Authorization: 'Bearer ' + token}})
}
intercept(req: HttpRequest<any>, next: HttpHandler): Observable<HttpSentEvent | HttpHeaderResponse | HttpProgressEvent | HttpResponse<any> | HttpUserEvent<any>> {
const authService = this.injector.get(ResetApiProvider);
return next.handle(this.addToken(req, authService.getAuthToken())).pipe(
catchError(error => {
if (error instanceof HttpErrorResponse) {
switch ((<HttpErrorResponse>error).status) {
case 400:
return this.handle400Error(error);
case 401:
return this.handle401Error(req, next);
default:
return _throw(error);
}
} else {
return _throw(error);
}
}));
}
//maybe use later for blacklist tokens
handle400Error(error) {
if (error && error.status === 400 && error.error && error.error.error === 'invalid_grant') {
// If we get a 400 and the error message is 'invalid_grant', the token is no longer valid so logout.
return this.logoutUser();
}
return _throw(error);
}
handle401Error(req: HttpRequest<any>, next: HttpHandler) {
if (!this.isRefreshingToken) {
this.isRefreshingToken = true;
// Reset here so that the following requests wait until the token
// comes back from the refreshToken call.
this.tokenSubject.next(null);
const authService = this.injector.get(ResetApiProvider);
return authService.refreshToken().pipe(
switchMap((newToken: string) => {
console.log('bbbbbbb');
if (newToken) {
this.tokenSubject.next(newToken);
return next.handle(this.addToken(req, newToken));
}
console.log('qqqq');
// If we don't get a new token, we are in trouble so logout.
return this.logoutUser();
}),
catchError(error => {
// If there is an exception calling 'refreshToken', bad news so logout.
return this.logoutUser();
}),
finalize(() => {
this.isRefreshingToken = false;
}),);
} else {
return this.tokenSubject.pipe(
filter(token => token != null),
take(1),
switchMap(token => {
return next.handle(this.addToken(req, token));
}),);
}
}
logoutUser() {
const authService = this.injector.get(ResetApiProvider);
authService.logout();
this.event.publish('UNAUTHORIZED');
return _throw("please login");
}
}
my refresh token function : 我的刷新令牌功能:
public refreshToken(): Observable<string> {
const url = `${apiUrl}/auth/refresh`;
console.log('fffff');
return this.http.post(url, {token: this.getAuthToken()},httpOptions)
.pipe(
map((res) => {
let token: any = res;
this.storage.set('token', token.data);
console.log(token.data);
this.currentToken = token.data;
return token.data;
catchError(this.handleError)
);
}
except, If the refreshToken() failed, the catch() and finally() are never reach in the AuthInterceptor class!! 否则,如果refreshToken()失败,则AuthInterceptor类中的catch()和finally()永远不会到达! How to fix that!?
如何解决!! so I can't clear storage and navigate to the login page.
因此我无法清除存储并导航至登录页面。
Try this tweak. 试试这个调整。
public refreshToken(): Observable<string> {
const url = `${apiUrl}/auth/refresh`;
console.log('fffff');
return this.http.post(url, {token: this.getAuthToken()},httpOptions)
.pipe(
map((res) => {
let token: any = res;
this.storage.set('token', token.data);
console.log(token.data);
this.currentToken = token.data;
//return token.data;
}),
catchError(this.handleError)
);
}
}),
between return and catchError. }),
在return和catchError之间。 Let me know if that helps. 让我知道是否有帮助。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.