我正在为使用访问令牌的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? –