我仍然是Angular的新手。我想刷新访问令牌,但不确定在哪里做。
我了解guards and
interceptors
。最好的地方在哪里?是否需要权衡取舍?
这里的许多问题都显示了在两种情况下该怎么做,但没有讨论“为什么”。我认为刷新应在请求周期的开始时在防护中进行,因此路由器知道是否要“激活”。但是,大多数示例都在拦截器中显示了它(通过查看到期时间或等待 401 然后刷新)。
任何建议将不胜感激。
更新
我知道“如何”,我需要理解的是为什么。正确的刷新位置在哪里?
警卫的工作是简单地检查用户是否已登录,如果不是,则重定向到登录页面。
如果刷新令牌已过期,那么我认为警卫队应该为canActivate(ActivatedRouteSnapshot, RouterStateSnapshot)
返回false,因为用户虽然已通过身份验证,但不再拥有当前授权。
这就是为什么我倾向于将其置于警卫状态。但是大多数示例(包括下面的出色示例)都显示了拦截器中的刷新。到那时肯定已经很晚了吗?我在这里缺少什么-这仅仅是样式问题,还是我应该考虑的角度请求周期还更多?
答案 0 :(得分:2)
您可以使用 HttpInterceptor 。由于每个API调用都通过槽拦截器,因此您可以检查令牌是否仍然有效,请继续进行API调用
如果令牌已过期,请显示烤面包机警报并阻止进一步的API调用。
有关使用拦截器的更多信息,请访问此10 ways to use Interceptors 和Angular 7 JWT Interceptor
完整代码:
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
}
]
session-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');
}