#angular #jwt #angular-router-guards
Вопрос:
Хорошая ли идея вызвать сервер в guard, чтобы проверить, действителен ли jwt?
Я храню jwt на интерфейсе, но я не знаю, истек ли срок действия этого токена или он внесен в черный список, если я не свяжусь с серверной частью. Кроме того, я не знаю роли пользователя, что важно для меня для AdminGuard.
Первая идея, которая у меня возникла, — это просто позвонить в серверную часть, и при таком подходе у меня будет вся необходимая информация, но главная проблема этого подхода заключается в том, что каждый раз, когда маршрут меняется, мне понадобится http-вызов.
После некоторых поисков я нашел библиотеку для angular, чтобы проверить jwt. А что касается ролей, я мог бы просто сохранить роль пользователя в качестве полезной нагрузки, а затем декодировать ее с помощью этой библиотеки jwt. Маркеры, занесенные в черный список, могут быть проблемой, но я думаю, что это редкий сценарий, и даже если охранник позволит этому пользователю продолжить движение по определенному маршруту, мой сервер просто вернет ошибку при первом запросе, и я перенаправлю.
Должен ли я попробовать второй подход? Или http-вызовы не имеют большого значения для охранников?
Ответ №1:
Теперь вот в чем дело, если вы хотите следовать рекомендациям, я бы рекомендовал использовать an interceptor
для проверки 401
несанкционированных ошибок (в основном это происходит, когда срок действия токенов истек). и в этом interceptor
случае вы можете вызвать login
метод из своей auth
службы, чтобы обновить свой токен и повторить запрос.
Вот пример кода:
import { Injectable } from '@angular/core';
import {
HttpRequest,
HttpHandler,
HttpInterceptor,
HttpErrorResponse,
} from '@angular/common/http';
import { Observable, throwError } from 'rxjs';
import { catchError, retry } from 'rxjs/operators';
import { Router } from '@angular/router';
import { StorageService } from 'src/app/services/storage.service';
import { AuthService } from 'src/app/modules/auth/auth.service';
import { User } from 'src/app/models/entities/user.interface';
import { ToastService } from 'src/app/services/toast.service';
import { NgxSpinnerService } from 'ngx-spinner';
@Injectable()
export class ErrorInterceptor implements HttpInterceptor {
constructor(
private _authService: AuthService,
private _storageService: StorageService,
) {}
//!Global scope error handling
intercept(request: HttpRequest<any>, next: HttpHandler): Observable<any> {
return next.handle(request).pipe(
// -> retry(1),
catchError((error: HttpErrorResponse) => {
if (error.error instanceof ErrorEvent) {
// handle client-side error
} else {
// handle server-side error
//-> i.e. 401, 404, 500, etc..
//-> Also refresh token for expired token
switch (error.status) {
case 401: //login
this._authService
.postLogin(this._storageService.getLocalObject('credentials'))
.subscribe((user: User) => {
this._storageService.setLocalObject('user', user);
this._storageService.setToken(user.jwtToken);
});
break;
case 403: //forbidden
break;
case 404: //not found
break;
case 500: //internal server error
break;
}
}
return throwError(error);
})
);
}
}
Держите все отдельно, чтобы увеличить возможность повторного использования. Так что это » нет » для вызова HTTP
запроса в вашем Guard
.