如何基于JWT令牌过期时间实现Angular应用自动登出?
解决Angular应用基于令牌过期时间自动登出的问题
你遇到的问题根源在于ngOnInit()只会在组件初始化时执行一次,只有页面刷新或组件首次加载时才会检查令牌状态,没法在令牌到期时自动触发登出。而且你的代码里还有个关键小错误:JWT的exp字段是秒级时间戳,但Date.now()返回的是毫秒级时间戳,直接比较会导致判断逻辑完全出错。
下面是完整的实现方案,能实现令牌到期时自动登出并跳转登录页:
步骤1:完善自动登出逻辑
我们需要计算令牌到期的剩余时间,设置定时器到期自动执行登出;同时处理页面刷新场景,初始化时就检查令牌是否已过期。
app.component.ts 完整代码
import { Component, OnInit, OnDestroy } from '@angular/core'; import { Router } from '@angular/router'; @Component({ selector: 'app-root', templateUrl: './app.component.html', styleUrls: ['./app.component.css'] }) export class AppComponent implements OnInit, OnDestroy { private logoutTimer: any; constructor(private router: Router) {} ngOnInit(): void { this.setupAutoLogout(); } ngOnDestroy(): void { // 组件销毁时清除定时器,避免内存泄漏 if (this.logoutTimer) { clearTimeout(this.logoutTimer); } } private setupAutoLogout(): void { const token = localStorage.getItem('token'); if (!token) { // 无令牌直接跳转登录页 this.router.navigate(['/login']); return; } // 手动解码JWT获取过期时间(exp是秒级时间戳,需转毫秒) const decodedToken = JSON.parse(atob(token.split('.')[1])); const expTimestamp = decodedToken.exp * 1000; const expiresIn = expTimestamp - Date.now(); if (expiresIn <= 0) { // 令牌已过期,立即登出 this.logout(); return; } // 设置定时器,到期自动登出 this.logoutTimer = setTimeout(() => { this.logout(); }, expiresIn); } logout(): void { // 清除令牌与定时器 localStorage.removeItem('token'); if (this.logoutTimer) { clearTimeout(this.logoutTimer); this.logoutTimer = null; } // 跳转登录页 this.router.navigate(['/login']); } }
步骤2:处理令牌更新场景
如果你的应用有刷新令牌逻辑(比如令牌到期前自动获取新令牌),记得在获取新令牌后调用setupAutoLogout(),清除旧定时器并设置新的,保证自动登出逻辑始终基于最新令牌有效期。
比如在登录或刷新令牌的方法中:
login(credentials) { return this.http.post('http://something/api/login/', credentials) .map(response => { const result = response.json(); if (result && result.token) { localStorage.setItem('token', result.token); // 登录成功后重新初始化自动登出定时器 this.appComponent.setupAutoLogout(); return true; } return false; }); }
关键注意点
- 时间戳单位转换:JWT的
exp是秒级时间戳,必须乘以1000转成毫秒后,再和Date.now()(毫秒级)比较,否则会出现“令牌未到期却被判定过期”的错误。 - 定时器清理:在组件销毁、手动登出、更新令牌时都要清除旧定时器,避免内存泄漏和重复触发登出。
- 路由守卫配合:可以结合Angular的
CanActivate路由守卫,在用户访问受保护路由时二次校验令牌状态,形成双重保障。
内容的提问来源于stack exchange,提问作者SamuraiJack
相关产品推荐
相关产品推荐

