我正在爲使用訪問令牌的API製作Angular 2前端。我正在嘗試使用observables和ngrx/store。Angular 2處理需要身份驗證令牌刷新的多個失敗請求
登錄和登出工作正常,並按預期工作。由於令牌過期,請求失敗時,我還寫了一些代碼。這段代碼通常工作正常,但當我在短時間內有多個請求時,我遇到了麻煩。例如,當我刷新頁面時,會發生這種情況,並且應用程序嘗試在應用程序中填充所需的兩到三個商店。
我的身份驗證服務具有這樣的功能:
refreshLogin(): Observable<any> {
const username = this.currentUser();
let query = new URLSearchParams();
query.set('refresh_token', this.refreshToken());
query.set('grant_type', 'refresh_token');
return this.getToken(username, query.toString());
}
private getToken(username: string, body: string): Observable<any> {
const url = Config.AUTH_TOKEN_PATH;
return this.http.post(url, body)
.map((res: Response) => res.json())
.do(
(data) => {
const token = {
username: username,
accessToken: data.access_token,
refreshToken: data.refresh_token,
tokenType: data.token_type,
expiresIn: data.expires_in
};
this.store.dispatch(AuthActions.loginSuccess(token));
},
error => {
const description = error.json().error_description;
this.store.dispatch(AuthActions.loginError(description));
console.error(error);
}
)
;
}
我的REST功能有這樣的函數:
get(url: string): Observable<any> {
return this.http.get(url, new RequestOptions({ headers: this.authHeader() }))
.catch(err => {
if (err.status === 401) {
return this.auth.refreshLogin()
.switchMap(() => this.http.get(url, new RequestOptions({ headers: this.authHeader() })))
.catch(err2 => err2);
} else {
console.log(err);
}
})
.map((res: Response) => res.json())
;
}
我不覺得功能currentUser()
,refreshToken()
,和authHeader()
是理解我的問題所必需的。
如果我有一個請求失敗和錯誤是401,我的應用程序調用refreshLogin()
,獲取新的訪問令牌,並將其存儲,和原來的請求與新的訪問令牌再次嘗試。
如果我有更多的失敗請求,並且它們同時發生,我會遇到問題。例如,假設我有兩個GET請求。他們都返回401錯誤。它們都會關閉refreshLogin()
功能。一個refreshLogin()
成功並存儲新的訪問令牌;另一個失敗,因爲用於刷新的令牌不再有效。這個功能流現在失敗了,導致我的應用程序停滯。
一個解決方案是將我的GET請求串聯起來,但似乎並不是這樣。
我覺得應該有一個解決方案,在失敗的GET(或其他)請求中,應用程序觸發刷新訪問令牌的調用。 auth服務會限制這些請求,所以每隔幾秒鐘就會有一次。它滿足了這個請求,並且新的訪問令牌被返回給所有請求以再次嘗試。
您是否認爲這是一種明智的方法,或者我只是試圖修補一種嚴重思考的方法?你會如何推薦讓這些零件互動?
嘿男人,你有解決這個問題嗎?如果是,你是如何解決它的,我遇到了和你一樣的問題。謝謝! –
Hi @SydneyLoteria。我確實解決了我的問題,謝謝。事實證明,我有正確的想法,但對rxjs沒有足夠的瞭解。我使用'.throttleTime(3000)'在三秒內停止多個刷新請求。不過,我應該補充一點,我也使用了@ ngrx/effects。所以它實際上是另一個被觀察的對象,然後可觀察對象調用'refreshToken'函數。我希望這是有道理的。 – freethebees
throttleTime對我來說是新的:)。所以,你的意思是我將在refreshToken服務上添加.throttleTime(3000),如果它們被多次調用,將導致停止所有活動的refreshToken? –