#javascript #angular #typescript #rxjs #jwt
#javascript #angular #typescript #rxjs #jwt
Вопрос:
Я реализую токен обновления JWT в своем проекте angular. Для этого я следую приведенному ниже руководству.
https://angular-academy.com/angular-jwt/
Вот мой код:
intercept(req: HttpRequest<any>, next: HttpHandler): Observable<HttpEvent<any>> {
const user: any = this.storage.user;
const addToken = !req.urlWithParams.includes('token');
const token = user ? user.token : null;
if (token amp;amp; !req.url.includes('token=') amp;amp; addToken) {
req = this.addToken(req, user.token);
}
return next.handle(req).pipe(switchMap((event) => {
if (event instanceof HttpResponse amp;amp; event.body.code === 401 amp;amp; token) {
return this.handle401Error(req, next);
}
return next.handle(req);
}));
}
private addToken(request: HttpRequest<any>, token: string) {
return request.clone({
setHeaders: {
Authorization: `Bearer ${token}`,
},
setParams: {
token
}
});
}
private handle401Error(request: HttpRequest<any>, next: HttpHandler) {
if (!this.isRefreshing) {
this.isRefreshing = true;
this.refreshTokenSubject.next(null);
return this.getRefreshedJWT().pipe(
switchMap((res: any) => {
this.isRefreshing = false;
this.refreshTokenSubject.next(res.token);
return next.handle(this.addToken(request, res.token));
}));
} else {
return this.refreshTokenSubject.pipe(
filter(token => token != null),
take(1),
switchMap(jwt => {
return next.handle(this.addToken(request, jwt));
}));
}
}
getRefreshedJWT() {
const jwt_refresh_url = 'api/v3/token/refresh?token=' this.storage.user.token;
return this.http.getFromAccountsApi(jwt_refresh_url)
.pipe(tap((token) => {
this.storeJwtToken(token);
}));
}
private storeJwtToken(jwt: string) {
const user = this.storage.user;
user.token = jwt;
this.storage.user = user;
}
Кстати. причина, по которой я не делаю этого внутри catchError
, заключается в том, что наш серверный сервер структурирован так, как будто он всегда будет отправлять код состояния HTTP 200, а внутри этого ответа они будут отправлять пользовательский http-код на основе ошибок, таких как 401, 500 или успеха, такого как 200 и т. Д. Таким образом, он не войдет внутрь catchError
, поскольку он ищет коды состояния HTTP, отличные от 200.
Теперь моя проблема заключается в том, что после реализации инициатора теперь мой API вызывается несколько раз. Смотрите Скриншот ниже:
Застрял со вчерашнего дня и пока не нашел подходящего решения. Было бы здорово, если бы кто-нибудь мог указать, что я здесь делаю, и как мне это решить?
Если у вас есть какие-либо дополнительные запросы, дайте мне знать. Спасибо..
Комментарии:
1. «наш серверный сервер структурирован так, как будто он всегда будет отправлять код состояния HTTP 200, и внутри этого ответа они будут отправлять пользовательский код http на основе ошибок, таких как 401, 500 или успеха, такого как 200 и т. Д.» . Маскирование ответов о состоянии не является хорошей практикой..
2. @iLuvLogix я понимаю, но ничего не могу с этим поделать. Это корпоративное приложение, и они делают это уже 3-4 года. Вот как они построили свой сервер.
Ответ №1:
Совет для:
Кстати. причина, по которой я не делаю этого внутри catchError, заключается в том, что наш серверный сервер структурирован так, как будто он всегда будет отправлять код состояния HTTP 200, и внутри этого ответа они будут отправлять пользовательский http-код на основе ошибки, такой как 401, 500 или успеха, такого как 200 и т.д. Таким образом, он не попадет внутрь catchError, поскольку он ищет коды состояния HTTP, отличные от 200.
Вы можете выполнить сопоставление в ответе от сервера и проверить, есть ли ошибка, а затем выдать оттуда ошибку, тогда catchError должен работать на последовательных каналах.
Ошибка заключается в том, что вы возвращаете дескриптор в switchMap, вызывая повторный запрос.
return next.handle(req);
Измените эту строку на:
return of(event)
И это должно сработать