Я пытался следовать следующим учебникам для реализации JWT refre sh в Angular 8, но безуспешно:
https://angular-academy.com/angular-jwt/#refresh -ken
https://github.com/tjgweb/curso-laravel-jwt-angular/blob/v20-21-22/web/src/app/interceptors/refresh-token.interceptor.ts
Я создал перехватчик, но если я не подпишусь, токен refre sh не будет работать. Если я подписываюсь на услугу токена refre sh, она работает, но мне приходится перезаряжать всю страницу из браузера.
Я использую Angular 8 + Ionic4
interceptor.ts
import { Injectable } from '@angular/core';
import {
HttpEvent,
HttpInterceptor,
HttpHandler,
HttpRequest,
HttpResponse,
HttpHeaders,
HttpErrorResponse,
HttpClient
} from '@angular/common/http';
import { Observable, from, BehaviorSubject, throwError } from 'rxjs';
import { tap, flatMap, catchError, mergeMap, switchMap, filter, take, finalize } from 'rxjs/operators';
import { environment } from '../environments/environment';
import { Router } from '@angular/router';
import { LoadingController } from '@ionic/angular';
import {NativeStorage} from '@ionic-native/native-storage/ngx';
import { SecurityService } from './services/security.service';
@Injectable()
export class APIInterceptor implements HttpInterceptor {
isLoading = false;
Token;
flagToken = false;
private isRefreshing = false;
private refreshTokenSubject: BehaviorSubject<any> = new BehaviorSubject<any>(null);
constructor(
private router: Router,
private http: HttpClient,
private loadingController: LoadingController,
private securityStorageService: SecurityService,
public nativeStorage: NativeStorage
) {
}
intercept(req: HttpRequest<any>, next: HttpHandler): Observable<HttpEvent<any>> {
console.log('URL INTERCEPTOR', `${environment.url}/${req.url}`);
if (req.url === 'Token') {
const apiReq = req.clone({ url: `${environment.url}/${req.url}` });
return next.handle(apiReq);
} else {
return from(this.securityStorageService.getToken()).pipe(mergeMap(
(token) => {
// tslint:disable-next-line:prefer-const
let newReq = req.clone(
{
headers: req.headers.set('Authorization', token)
.set('Authorization-Type', 'JWT')
.set('Content-Type', 'application/json')
.set('Cache-Control', 'no-cache')
.set('Pragma', 'no-cache'),
url: `${environment.url}/${req.url}`
});
this.presentLoading();
return next.handle(newReq).pipe(
tap(event => {
if (event instanceof HttpResponse) {
console.log('Interceptor - HttpResponse = ' + event.status); // http response status code
this.dismissLoading();
}
}, error => {
this.dismissLoading();
// http response status code
if (error instanceof HttpErrorResponse) {
console.log('----response----');
console.error('status code:');
console.log('ERRORE CALLBACK', error);
console.error(error.status);
console.error(error.message);
console.log('--- end of response---');
if (error.status === 401) {
console.log('401');
return this.handle401Error(newReq, next);
} else {
return throwError(error);
}
}
// return Observable.throw(error);
})
);
}
));
}
}
private handle401Error(request: HttpRequest<any>, next: HttpHandler) {
console.log('ISREFRESHING VALUE', this.isRefreshing);
if (!this.isRefreshing) {
console.log('JWT IN IF SUBJECT');
this.isRefreshing = true;
this.refreshTokenSubject.next(null);
console.log('REFRESH SUBJECT NULL');
let params = {};
this.nativeStorage.getItem('refreshToken').then(
(data) => {
console.log('NATIVE STORAGE RTOKEN', data);
params = {
RToken: data
};
return this.securityStorageService.refreshToken(params).pipe(
switchMap((token: any) => {
console.log('SWITCHMAP TOKEN', token);
this.isRefreshing = false;
this.refreshTokenSubject.next(token.Token);
return next.handle(this.addToken(request, token.Token)).pipe(
tap(error => {console.log('ERRORE IN NEXT HANDLE', error)})
);
}),
catchError(err => {
console.log('ERRORE REFRESH TOKEN - LOGOUT APP', err);
return this.router.navigate(['/login']);
}),
finalize(() => {
this.isRefreshing = false;
})
)/*.subscribe(
(rs) => {console.log('TOKEN REFRESH SUBSCRIBE', rs);}
);*/
}
);
} else {
console.log('ELSE SUBJECT TOKEN');
return this.refreshTokenSubject.pipe(
filter(token => token != null),
take(1),
switchMap(jwt => {
console.log('JWT IN ELSE SUBJECT', jwt);
return next.handle(this.addToken(request, jwt.Token));
}));
}
}
private addToken(request: HttpRequest<any>, token: string) {
return request.clone({
headers: request.headers.set('Authorization', token)
.set('Authorization-Type', 'JWT')
.set('Content-Type', 'application/json')
.set('Cache-Control', 'no-cache')
.set('Pragma', 'no-cache')
// url: `${environment.url}/${request.url}`
});
}
// Creación del loading
async presentLoading() {
this.isLoading = true;
return await this.loadingController.create({
message: 'Caricamento in corso...',
translucent: true,
duration: 1000,
}).then(a => {
a.present().then(() => {
if (!this.isLoading) {
a.dismiss().then(() => console.log());
}
});
});
}
// Cierre del loading
async dismissLoading() {
this.isLoading = false;
return await this.loadingController.dismiss().then(() => console.log('dismissed'));
}
}
security.service.ts
import { Injectable } from '@angular/core';
import { NativeStorage } from '@ionic-native/native-storage/ngx';
import { HttpClientModule, HttpClient } from '@angular/common/http';
import { tap, catchError } from 'rxjs/operators';
import { Tokens } from '../models/tokens';
import { Observable, throwError } from 'rxjs';
@Injectable({
providedIn: 'root'
})
export class SecurityService {
constructor(public nativeStorage: NativeStorage, private http: HttpClient) { }
public async getToken() {
return await this.nativeStorage.getItem('token');
}
refreshToken(params) {
return this.http.post<any>(`RToken/?`, params)
.pipe(tap((risultato: Tokens) => {
console.log('TOKEN FROM SERVER', risultato);
this.nativeStorage.setItem('token', risultato.token);
this.nativeStorage.setItem('refreshToken', risultato.refreshToken);
}),
catchError(err => {
console.log('ERRORE CHIAMATA RTOKEN', err);
return throwError(err);
})
);
}
}
Спасибо