angular 2 http异常处理程序和jwt刷新 [英] angular 2 http exception handler and jwt refresh
问题描述
当我遇到某个异常时,我正在尝试刷新JWT令牌,这是我的错误处理程序应该处理它们的另一个异常。
I am trying to refresh a JWT token when I got a certain exception, when it is another exception my ErrorHandler should handle them.
我有一段代码,令牌刷新工作的地方,以及异常处理程序工作的一段代码,但我不能以工作方式组合它们。
I have one piece of code, one where the token refresh works, and one piece of code where the exception handler works, but I just can't combine them in a working way.
问题是我不能抛出一个异常,并在一个observable中用我的ErrorHandler捕获它。
The problem is that I can't throw an exception and catch it with my ErrorHandler in an observable.
这是我可以刷新我的令牌的代码。当它失败时,它检查错误代码是否是 token_expired
,当它是刷新令牌并重试请求时。
Here is the code where I can refresh my token with. When it fails it checks if the error code is token_expired
, when it is it will refresh the token and retry the request.
export class HttpErrorService extends Http {
constructor(backend: XHRBackend, defaultOptions: RequestOptions) {
super(backend, defaultOptions);
}
request(url: string | Request, options?: RequestOptionsArgs, disableRefresh = false): Observable<Response> {
return super.request(url, options).catch((error: Response) => {
// Refresh token on token_expired exception.
if (!disableRefresh && error.status === 401 && error.json().error.code === 'token_expired') {
return this.renewToken().flatMap((response) => {
const res = response.json();
// Replace the token in storage.
localStorage.setItem('__token', res.data.token);
// Replace request the token with the new one.
if (url instanceof Request) {
url.headers.set('Authorization', 'Bearer ' + res.data.token);
} else if (options) {
options.headers.set('Authorization', 'Bearer ' + res.data.token);
}
// To prevent a loop disable refreshing at the next request.
return this.request(url, options, true);
});
}
// Here I want to throw the exception.
// I need to be able to catch it with my exception handler.
// throw error; doesn't work.
return Observable.throw(error);
});
}
private getBaseUrl(): string {
return environment.base_uri;
};
renewToken(): Observable<Response> {
const headers = new Headers();
headers.append('Authorization', 'Bearer ' + localStorage.getItem('__token'))
return this.post(this.getBaseUrl() + '/auth/refresh', {}, {headers: headers});
}
}
以上唯一不好的是我可以在我的异常处理程序中捕获异常。
The only bad thing about the above is that I can't catch the exception in my exception handler.
以下代码可以抛出ErrorHandler可以捕获的异常。但是我不知道如何在一次调用中刷新令牌...
The following code can throw exceptions that can be catched by the ErrorHandler. But I have no idea how I can refresh the token in one call...
export class HttpErrorService extends Http {
constructor(backend: XHRBackend, defaultOptions: RequestOptions) {
super(backend, defaultOptions);
}
request(url: string | Request, options?: RequestOptionsArgs, disableRefresh = false): Observable<Response> {
return Observable.create(observer => {
super.request(url, options).subscribe(
res => observer.next(res),
err => {
if (!disableRefresh && err.status === 401 && err.json().error.code === 'token_expired') {
// I can't return this.renewToken()...
}
observer.error(err);
throw new HttpException(err); // this is getting catched by the ErrorHandler
},
() => observer.complete);
});
}
private getBaseUrl(): string {
return environment.base_uri;
};
renewToken(): Observable<Response> {
const headers = new Headers();
headers.append('Authorization', 'Bearer ' + localStorage.getItem('__token'))
return this.post(this.getBaseUrl() + '/auth/refresh', {}, {headers: headers});
}
}
我的错误处理程序只包含 console.log()
。
https: //angular.io/api/core/ErrorHandler
My error handler is only contains a console.log()
.
https://angular.io/api/core/ErrorHandler
我怎样才能使这个工作?
How can I get this working?
推荐答案
几个小时后我终于得到了解决方案!
After some hours I finally got the solution!
export class HttpErrorService extends Http {
constructor(backend: XHRBackend, defaultOptions: RequestOptions) {
super(backend, defaultOptions);
}
request(url: string | Request, options?: RequestOptionsArgs, disableRefresh = false): Observable<Response> {
return Observable.create(observer => {
super.request(url, options).retryWhen(attempts => this.retryRequest(attempts)).catch((error: Response) => {
// Refresh token on token_expired exception.
if (!disableRefresh && error.status === 401 && error.json().error.code === 'token_expired') {
return this.renewToken().flatMap((response) => {
const res = response.json();
// Replace the token in storage.
localStorage.setItem('__token', res.data.token);
// Replace request the token with the new one.
if (url instanceof Request) {
url.headers.set('Authorization', 'Bearer ' + res.data.token);
} else if (options) {
options.headers.set('Authorization', 'Bearer ' + res.data.token);
}
// To prevent a loop disable refreshing at the next request.
return this.request(url, options, true);
});
}
throw Observable.throw(error);
}).subscribe(
res => observer.next(res),
err => {
observer.error(err);
throw new HttpException(err);
}
);
});
}
private getBaseUrl(): string {
return environment.base_uri;
};
renewToken(): Observable<Response> {
const headers = new Headers();
headers.append('Authorization', 'Bearer ' + localStorage.getItem('__token'))
return this.post(this.getBaseUrl() + '/auth/refresh', {}, {headers: headers});
}
retryRequest(attempts: any) {
let count = 0;
return attempts.flatMap(error => {
return ++count >= 3 ? Observable.throw(error) : Observable.timer(count * 1000);
});
}
}
这篇关于angular 2 http异常处理程序和jwt刷新的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!