我有一个 Angular 13 应用程序。我在那里使用 JWT 令牌进行身份验证。一切正常。但我给 JWT 令牌的令牌过期时间是 1 小时。一旦服务器端的令牌过期,我想从前端应用程序中注销用户。
我这样做了,但似乎有问题并且对我不起作用:
export class authInterceptor implements HttpInterceptor {
constructor(private userService: UserService) {
}
intercept(request: HttpRequest<any>, next: HttpHandler): Observable<HttpEvent<any>> {
if (this.userService.isAuthentificated()) {
request = request.clone({
setHeaders: {
Authorization: `Bearer ${this.userService.getToken()}`
}
});
}
return next.handle(request).pipe(
tap(event => {
}, error => {
this.onSubscribeError(error);
})
);
}
private onSubscribeError(error: any): void {
if (error.status === 401 || error.status === 403) {
this.userService.logout();
}
}
}
任何人都可以告诉我我做错了什么并帮助我改正吗?
E. Maggini 提供的链接从技术上来说很好,但至少接受的答案仅与让服务器决定它是否过期有关。
如果您没有调用服务器并收到 401,您的 UI 将保持登录状态,直到您这样做为止。
你需要两者的结合;添加到您的拦截器中以检查您的 401 并注销您(当然),并且应用程序本身会检查令牌。
最简单的方法就是在旅途中留出一段时间检查令牌是否过期。
假设您有某种具有基本登录/注销处理功能的单例
AuthService
...
@Injectable()
export class AuthService {
private jwt: string;
private expiryTimer: any;
public login(jwt: string): void {
this.jwt = jwt;
this.expiryTimer = setInterval(() => { this.checkExpiry(); }, 60000);
this.router.navigate(['...']);
}
public logout(): void {
this.jwt = undefined;
if (this.expiryTimer) clearInterval(this.expiryTimer);
this.router.navigate(['...']);
}
private checkExpiry(): void {
if (this.jwtService.hasExpired(this.jwt)) this.logout();
}
}
假设您有一些 jwt 服务或方法或其他东西来检查过期时间...
它看起来会比这更复杂,因为据推测,您实际上会将令牌存储在某个地方(本地存储?),以便处理页面刷新等。
但基础知识就在那里 - 不要想太多,它就像每隔 x 检查一次令牌(1m 足够好吗?)一样简单,如果它过期,则注销...
您修改后的拦截器将使用相同的东西;得到 401 吗?
this.authService.logout();
。完成。
// Create HttpInterceptor class like yours and follow the steps as mentioned
@Injectable()
export class JwtInterceptor implements HttpInterceptor {
// Inject your AuthService
constructor(private authService: AuthService) { }
intercept(request: HttpRequest<unknown>, next: HttpHandler): Observable<HttpEvent<unknown>> {
// Find your login response from authService
const loginResponse = this.authService.getLoginResponse()
// Check loginResponse?.token has any token
if (loginResponse?.token) {
// Check expire time coming from server response
let tokenExpirationDate: any = new Date(loginResponse?.expiresAt);
if ((tokenExpirationDate > new Date())) {
request = request.clone({
setHeaders: {
Authorization: `Bearer ${loginResponse.token}`
}
});
}
else {
// Call logout
this.authService.logout();
}
}
else {
request = request.clone({
setHeaders: {
Authorization: ""
}
});
}
return next.handle(request);
}
}