You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何基于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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.27 07:11:37