Я все еще новичок в Angular. Я хочу обновить токен доступа, но не знаю, где это сделать.
Я знаю о guards andinterceptors. Где лучше всего это сделать? Есть ли компромиссы, которые я должен принять во внимание?
Многие вопросы здесь показывают, как это сделать в любом случае, но не обсуждают «почему». Я думаю, что обновление должно происходить в стороже, в самом начале цикла запроса, чтобы маршрутизатор знал, нужно ли «активировать». Но большинство примеров показывают это в перехватчике (либо просматривая время истечения срока действия, либо ожидая 401, а затем обновляя).
Любой совет будет принят во внимание.
ОБНОВЛЕНИЕ
Я знаю «как», мне нужно понять, почему. Где правильное место для обновления?
Задача охранника — просто проверить, вошел ли пользователь в систему, и, если нет, перенаправить на страницу входа.
Если срок действия токена обновления истек, я считаю, что охранник должен вернуть false для canActivate(ActivatedRouteSnapshot, RouterStateSnapshot), потому что пользователь, хотя и прошел проверку подлинности, больше не имеет текущего гранта.
Вот почему я склоняюсь к тому, чтобы поставить его в охрану. Но большинство примеров, в том числе превосходный приведенный ниже, показывают обновление в перехватчике. Несомненно, к тому времени это уже очень поздно в цикле запроса? Что мне здесь не хватает - это только вопрос стиля, или есть еще цикл запроса angular, который я должен учитывать?





Вы можете использовать HttpInterceptor. Поскольку каждый вызов API проходит через перехватчик, вы можете проверить, действителен ли токен, и продолжить вызов API.
Если срок действия токена истек, покажите предупреждение toastr и предотвратите дальнейшие вызовы API.
Для получения дополнительной информации об использовании перехватчика посетите эти 10 способов использования перехватчиков и Угловой 7 Перехватчик JWT.
Complete Code:
http-interceptor.service.ts
import { Injectable } from '@angular/core';
import { HttpInterceptor, HttpRequest, HttpHandler, HttpEvent, HttpResponse } from '@angular/common/http';
import { Observable } from 'rxjs';
import { tap } from 'rxjs/operators';
import { SessionService } from './session.service';
import { Router } from '@angular/router';
import { throwError } from 'rxjs';
declare var toastr;
@Injectable({
providedIn: 'root'
})
export class HttpInterceptorService implements HttpInterceptor {
constructor(private router: Router, private sessionService: SessionService) { }
intercept(req: HttpRequest<any>, next: HttpHandler): Observable<HttpEvent<any>> {
var token = this.sessionService.getToken();
if (token != null && this.sessionService.isTokenExpired()) {
this.sessionService.logOut()
toastr.warning("Session Timed Out! Please Login");
this.router.navigate(['/login'])
return throwError("Session Timed Out")
} else {
const authRquest = req.clone({
setHeaders: {
Authorization: 'Bearer ' + token
}
})
return next.handle(authRquest)
.pipe(
tap(event => {
}, error => {
})
)
}
}
}
app.module.ts
providers: [
{
provide: HTTP_INTERCEPTORS,
useClass: HttpInterceptorService,
multi: true
}
]
сеанс-service.ts
getToken(): string {
return localStorage.getItem('userToken');
}
getTokenExpirationDate(token: string): Date {
token = this.getToken()
const decoded = jwt_decode(token);
if (decoded.exp === undefined) return null;
const date = new Date(0);
date.setUTCSeconds(decoded.exp);
return date;
}
isTokenExpired(token?: string): boolean {
if (!token) token = this.getToken();
if (!token) return true;
const date = this.getTokenExpirationDate(token);
if (date === undefined) return false;
return !(date.valueOf() > new Date().valueOf());
}
logOut(loginType?: string) {
localStorage.removeItem('isLoggedin');
localStorage.removeItem('userRole');
}
Interceptor это место, чтобы сделать это. В Guard мы фактически оцениваем, имеет ли пользователь (вошедший в систему) доступ к маршруту. И Guard — это место для проверки маршрутизации, оно не связано с HTTP-вызовами, а токены связаны с Http-вызовами, которые должны обрабатываться в interceptorsОоо... теперь я понимаю. Таким образом, охранник должен только проверить, является ли пользователь разрешается для доступа к этому маршруту - действительно ли он вошел в систему или нет, на этом этапе не имеет значения. Спасибо за разъяснения! :)
Честно говоря, я проверил репо на ту ссылку, которую вы разместили, и это подтвердило мои подозрения. Я не уверен, что охрана - лучшее место. Он не выполняет какую-либо операцию ACL — он проверяет, вошел ли пользователь в систему, и, если нет, перенаправляет на страницу входа. Если срок действия токена обновления истек, то ответ на canActivate(route: ActivatedRouteSnapshot, state: RouterStateSnapshot) должен быть ложным. Я считаю, что охрана - это место, где можно это сделать, но я новичок, поэтому могу ошибаться.
Я хочу оставить вопрос открытым еще немного, чтобы получить больше идей. Вы, вероятно, правы, но я хочу посмотреть, какие компромиссы упоминают люди.
Конечно.. Я поделился всем, что знаю. Может быть я не прав или прав частично, я работал над несколькими проектами в двух организациях, и везде используется подход interceptor
Ваш пример по-прежнему великолепен, независимо от того, идет ли код в охрану или перехватчик, я буду его использовать! :-)
Спасибо. Это скопировано из живого проекта :)
Спасибо за этот очень хороший и очень полный пример! Однако мне интересно, лучше ли это делать в перехватчике, как вы показали, или в охраннике. Хотя я новичок в angular, моя интуиция подсказывает мне, что охранник — лучшее место, потому что именно там вы решаете, активировать ли маршрут. Но большинство примеров похожи на этот, и я не уверен, что это проблема стиля, или я чего-то не понимаю...