当我登录 API 向我发送token和token-life-time 时,当token-life-time即将结束时,我通过向 API 发送请求来刷新我的token并接收新的 token 和新的 refresh-token-time。
当我刷新或导航到另一个页面时(在令牌生命周期结束的那一刻),我的拦截器发送令牌的旧值,当我再次刷新或导航到另一个页面时LocalStorage,API 给我一个错误“令牌不正确”发送正确的令牌。
但是如上所述,当令牌生命周期即将结束时,它会重复。
这是我的token-interceptor.service.ts
import { Injectable } from '@angular/core';
import { HttpEvent, HttpInterceptor, HttpHandler, HttpRequest, HttpHeaders } from '@angular/common/http';
import { Observable } from 'rxjs';
import { LoginService } from '../services/login.service';
@Injectable()
export class TokenInterceptorService implements HttpInterceptor {
constructor(
private loginService: LoginService
) { }
intercept(request: HttpRequest<any>, next: HttpHandler): Observable<HttpEvent<any>> {
if (
this.loginService.isLogged
) {
const token = localStorage.getItem('access-token');
const headers = new HttpHeaders().set('Authorization', `Bearer ${token}`);
request = request.clone({ headers: headers });
}
return next.handle(request);
}
}
它需要令牌并向 API 发送请求。
我有login.service.ts登录和刷新功能。登录函数将令牌值放入LocalStorage并且如果var 为 true 并且它运行良好,则Refresh 函数会刷新令牌。LocalStorageisNeedToRefresh
refresh(): Observable<boolean> {
return this.http.post(`${environment.auth}/refresh`, {
token_hash: localStorage.getItem('refresh-token')
}).pipe(
map((res: any) => {
if (res.access && res.refresh) {
localStorage.setItem('access-token', res.access.hash);
localStorage.setItem('expires-at-access', res.access.expires_at);
localStorage.setItem('refresh-token', res.refresh.hash);
localStorage.setItem('expires-at-refresh', res.refresh.expires_at);
return true;
} else {
this.notificationService.error(res && res.result_descr || '');
return false;
}
}),
catchError(() => of(false))
);
}
这是我刷新令牌的地方login.component.ts
ngOnInit() {
if (this.loginService.isLogged) {
if (this.loginService.isNeedToRefresh === true) {
this.loginService.refresh().subscribe((res: boolean) => {
if (res === true) {
this.router.navigate(['']);
}
});
} else if (this.loginService.isNeedToRefresh === false) {
this.router.navigate(['']);
}
}
}
我也更新了我的令牌app.component.ts
ngOnInit() {
$(document).on('click', '[href="#"]', e => e.preventDefault());
this.router.events.subscribe((val) => {
if (val instanceof NavigationEnd) {
if (!(val.url.indexOf('/login') === 0)) {
this.authWatcher();
}
}
});
}
authWatcher() {
if (this.loginService.isLogged) {
if (this.loginService.isNeedToRefresh === true) {
this.loginService.refresh().subscribe((refresh: boolean) => {
if (refresh === false) {
this.authModalRef = this.modalService.show(this.staticModal, { backdrop: 'static' });
} else {
this.loginService.checkToken().subscribe((check: boolean) => {
if (!check) {
this.logoutService.logout();
this.router.navigate(['login']);
}
});
}
});
}
}
我的拦截器运行良好的最佳方式是什么?
一点点更新,这是我检查 isNeedToRefresh 的方法
get isNeedToRefresh(): boolean {
const accessExpireTimestamp = new Date(
localStorage.getItem('expires-at-access')
).getTime();
const refreshExpireTimestamp = new Date(
localStorage.getItem('expires-at-refresh')
).getTime();
const nowTimestamp = new Date().getTime();
if (nowTimestamp >= accessExpireTimestamp) {
if (nowTimestamp >= refreshExpireTimestamp) {
return null; // Refresh token expired
} else {
return true; // Refresh token not expired
}
}
return false;
}