我想使用全局錯誤處理程序處理訪問令牌,並使用刷新令牌刷新它們。我的解決方案,幾乎似乎工作如下:Angular 2:如何在全局範圍內處理http oauth authtoken 401錯誤
ROM您的組件,訂閱可觀察到如下:
this.myHttpService.getSomeData().subscribe(response => {
console.log('user logged in', response);
},
error => {
// optionally do something custom here.
console.log(error);
throw error;
// we could handle the error here, getting the new auth token and calling this again.
}
上面的錯誤處理程序是沒有必要的,因爲我們可以在全球處理錯誤錯誤處理程序,但您可能需要在此處理其他事情。
在我的http服務,我有一個函數返回一個可觀察到的是這樣的:1。 捕捉錯誤 2.認識到:
getSomeData(): Observable<any> {
return this.http.get(this.API_URL_BASE + '/api/activities/getsomeData, this.httpHelperMethodsService.defaultOptions).map((response: Response) => {
return response.json();
}).catch(this.handleError);
}
來處理身份驗證令牌到期將是如下過程身份驗證令牌已過期 3.調用來獲得一個新的身份驗證令牌使用刷新令牌 4.重新運行源可觀察
在服務上,實現處理錯誤的功能,它看起來像這樣:
private handleError(error: any, originalObservable: any) {
let errorHelper = { 'error': error, 'observable': originalObservable};
return Observable.throw(errorHelper);
}
然後,您可以創建一個全局錯誤處理程序如下:
@Injectable()
export class ApplicationErrorHandler extends ErrorHandler {
constructor(private injector: Injector) {
super(false);
}
handleError(error: any): void {
const refreshTokenService = this.injector.get(RefreshTokenService);
...
else if(error.statusText == "Unauthorized"){
// check if token is expired. This will involve looking in local storage and comparing expiry time to current time.
if(isTokenExpired){
refreshTokenService.refreshToken(refreshToken).subscribe(response => {
// set refresh token
error.observable().subscribe(response => {
// return response.
}, error => {
// return error.
})
}
}
}
}
}
使用HTTP攔截,其配置如下:
import {Injectable} from "@angular/core";
import { ConnectionBackend, RequestOptions, Request, RequestOptionsArgs, Response, Http, Headers} from "@angular/http";
import {Observable} from "rxjs/Rx";
@Injectable()
export class InterceptedHttp extends Http {
constructor(backend: ConnectionBackend, defaultOptions: RequestOptions) {
super(backend, defaultOptions);
}
request(url: string | Request, options?: RequestOptionsArgs): Observable<Response> {
return super.request(url, options);
}
get(url: string, options?: RequestOptionsArgs): Observable<Response> {
return super.get(url, this.getRequestOptionArgs(options));
}
post(url: string, body: string, options?: RequestOptionsArgs): Observable<Response> {
return super.post(url, body, this.getRequestOptionArgs(options));
}
put(url: string, body: string, options?: RequestOptionsArgs): Observable<Response> {
return super.put(url, body, this.getRequestOptionArgs(options));
}
delete(url: string, options?: RequestOptionsArgs): Observable<Response> {
return super.delete(url, this.getRequestOptionArgs(options));
}
private getRequestOptionArgs(options?: RequestOptionsArgs) : RequestOptionsArgs {
return this.getOptionsWithAccessToken();
}
getOptionsWithAccessToken() {
let accessToken = localStorage.getItem('access_token');
let accessTokenJson = <any>JSON.parse(accessToken);
let headers = new Headers();
headers.append('Content-Type', 'application/json');
headers.append('Accept', 'application/json');
headers.append('Authorization', accessTokenJson);
let options = new RequestOptions({ headers: headers });
console.log('options updated', options);
return options;
}
}
的HTTP但是,當再次訂閱原始的observable時,不會調用攔截器,而只是獲得另一個401.我可以根據日誌語句console.log('options updated', options);
這個攔截器在所有其他http調用之前被調用。看起來,http攔截器在你訂閱原始觀察器時不運行,是這種情況嗎?
有沒有辦法更新此observable上的選項以使用新的身份驗證令牌?也許我可以在observable上調用其他方法之一而不是訂閱?或者這是不可能的?我能想到的唯一選擇就是在每個http調用中捕獲錯誤,但我有大約一百個,所以寧可不要這樣做。
https://angular.io/guide/http#intercepting-all-requests-or-responses –
謝謝。是的,這聽起來像是解決方案。如果授權令牌設置在攔截器中,則它將按預期設置。 我現在要回家了,明天再試。 – Sam
@JBNizet我已經更新了這個問題,以包括我使用http攔截器的嘗試,但不幸的是,這並沒有奏效。 – Sam