Я впервые работаю с угловыми перехватчиками, и у меня почти есть то, что я хочу, но есть кое-что, что я не могу понять даже после того, как некоторое время гуглюсь. Я храню токен обновления локально, и токен доступа истекает каждые 15 минут; Я хочу использовать токен обновления для автоматического обновления их токена аутентификации по истечении срока действия.
Моя первая попытка прошла так:
intercept(req: HttpRequest<any>, next: HttpHandler): Observable<HttpEvent<any>> {
if (req.url.toLowerCase().includes('/auth')) {
// It's an auth request, don't get a token
return next.handle(req);
}
// Not an auth endpoint, should have a token
this.authService.GetCurrentToken().subscribe(token => {
// Make sure we got something
if (token == null || token === '') {
return next.handle(req);
}
// Have a token, add it
const request = req.clone({
setHeaders: {
Authorization: `Bearer ${token}`
}
});
return next.handle(request);
});
}
Похоже, это не сработало, и я не мог понять почему (я новичок в Angular и довольно новичок в JS, так что извините, если это очевидно для других). На догадке я подумал, не было ли это наблюдаемой путаницей, и ему не нравится ждать, пока наблюдаемое вернется, поэтому я попробовал это:
intercept(req: HttpRequest<any>, next: HttpHandler): Observable<HttpEvent<any>> {
if (req.url.toLowerCase().includes('/auth')) {
// It's an auth request, don't get a token
return next.handle(req);
}
const token = this.authService.GetAccessTokenWithoutRefresh();
const request = req.clone({
setHeaders: {
Authorization: `Bearer ${token}`
}
});
return next.handle(request);
}
А теперь похоже на работу! Это говорит о том, что я мог быть прав в своей догадке (или что это что-то еще внутри другого кода, который я не вижу). В любом случае, работа - это хорошо, но у меня остается вопрос, как освежиться. Первоначальная причина, по которой я использовал это с помощью наблюдаемой службы аутентификации, заключалась в том, что нужно было обновить. По сути, служба аутентификации проверяет свой текущий токен и определяет, истек ли он или нет. Если нет, он просто вернет of(token)
, но если срок его действия истечет, он обратится к серверу через сообщение http, которое можно наблюдать, поэтому строка будет поступать всякий раз, когда сервер отвечает.
Так что я думаю, мой вопрос двоякий:
- Может ли кто-нибудь подтвердить или опровергнуть, что я был прав насчет наблюдаемой путаницы с перехватчиком? Кажется, что это проблема, но хотелось бы быть уверенным.
- Как мне справиться с обновлением токена для них в фоновом режиме без необходимости повторного входа каждые 15 минут?
EDIT
Вот логика в методе аутентификации:
GetCurrentToken(): Observable<string> {
if (this.AccessToken == null) {
return null;
}
if (this.Expiry > new Date()) {
return of(this.AccessToken);
}
// Need to refresh
return this.RefreshToken().pipe(
map<LoginResult, string>(result => {
return result.Success ? result.AccessToken : null;
})
);
}
и метод обновления:
private RefreshToken(): Observable<LoginResult> {
const refreshToken = localStorage.getItem('rt');
if (refreshToken == null || refreshToken === '') {
const result = new LoginResult();
// Set other stuff on result object
return of(result);
}
const refresh = new RefreshTokenDto();
refresh.MachineId = 'WebPortal';
refresh.TokenId = refreshToken;
return this.http.post(ApiData.baseUrl + '/auth/refresh', refresh)
.pipe(
tap<AuthResultDto>(authObject => {
this.SetLocalData(authObject);
}),
map<AuthResultDto, LoginResult>(authObject => {
const result = new LoginResult();
// Set other stuff on the result object
return result;
}),
catchError(this.handleError<LoginResult>('Refresh'))
);
}