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

如何在Angular 2/5项目中为本地存储设置类.Net会话超时?

在Angular 2/5中实现类似.Net的会话超时功能

我之前在Angular项目里做过类似的会话超时需求,结合本地存储和session变量的话,可以按下面这几步来操作,亲测好用:

1. 登录时记录会话关键信息

登录成功后,把登录时间、超时时长(比如30分钟)以及用户的session数据存在本地存储里,这样页面刷新后也能恢复会话状态:

// 登录成功后的处理逻辑
login(userCredentials: any) {
  // 调用登录接口获取session信息
  this.authService.login(userCredentials).subscribe((response) => {
    // 保存session数据到sessionStorage(比localStorage更安全,关闭浏览器自动清除)
    sessionStorage.setItem('userSession', JSON.stringify(response.session));
    // 记录登录时间戳(毫秒)
    sessionStorage.setItem('loginTimestamp', new Date().getTime().toString());
    // 设置超时时长,比如30分钟=1800000毫秒
    sessionStorage.setItem('sessionTimeout', '1800000');
    // 初始化超时计时器
    this.sessionTimeoutService.initTimeout();
  });
}

2. 封装会话超时服务

创建一个SessionTimeoutService来统一管理超时逻辑,里面包含监听用户活动、重置计时器、触发超时登出的功能:

import { Injectable } from '@angular/core';
import { Router } from '@angular/router';
import { Subject } from 'rxjs';

@Injectable({ providedIn: 'root' })
export class SessionTimeoutService {
  private timeoutTimer: any;
  private timeoutDuration: number;
  // 用于通知其他组件会话已过期
  public sessionExpired$ = new Subject<void>();

  constructor(private router: Router) {}

  initTimeout() {
    // 从存储中获取超时时长
    this.timeoutDuration = parseInt(sessionStorage.getItem('sessionTimeout') || '1800000', 10);
    // 清除之前的计时器(避免重复触发)
    this.clearAllTimers();
    // 设置新的超时计时器
    this.setTimeout();
    // 监听用户活动,有操作就重置计时
    this.listenToUserActions();
  }

  private setTimeout() {
    this.timeoutTimer = setTimeout(() => {
      // 超时后执行登出逻辑
      this.handleSessionExpiry();
    }, this.timeoutDuration);
  }

  private clearAllTimers() {
    if (this.timeoutTimer) {
      clearTimeout(this.timeoutTimer);
    }
  }

  private listenToUserActions() {
    // 监听用户常见操作:鼠标移动、键盘输入、点击、滚动
    const activityEvents = ['mousemove', 'keydown', 'click', 'scroll'];
    activityEvents.forEach(event => {
      window.addEventListener(event, () => this.resetTimeout());
    });
  }

  private resetTimeout() {
    // 用户有操作就重置计时器
    this.clearAllTimers();
    this.setTimeout();
    // 更新登录时间戳,让超时计算更精准
    sessionStorage.setItem('loginTimestamp', new Date().getTime().toString());
  }

  private handleSessionExpiry() {
    // 清除存储中的会话数据
    sessionStorage.removeItem('userSession');
    sessionStorage.removeItem('loginTimestamp');
    sessionStorage.removeItem('sessionTimeout');
    // 通知所有订阅组件会话过期
    this.sessionExpired$.next();
    // 跳转到登录页
    this.router.navigate(['/login']);
  }

  // 手动登出时调用,统一清除资源
  logout() {
    this.handleSessionExpiry();
  }
}

3. 页面刷新后恢复超时逻辑

在根组件(比如AppComponent)的ngOnInit里检查是否存在有效会话,如果有的话重新初始化超时服务,避免页面刷新后超时逻辑失效:

import { Component, OnInit } from '@angular/core';
import { SessionTimeoutService } from './services/session-timeout.service';

@Component({
  selector: 'app-root',
  templateUrl: './app.component.html'
})
export class AppComponent implements OnInit {
  constructor(private sessionTimeoutService: SessionTimeoutService) {}

  ngOnInit() {
    // 检查是否有已登录的会话
    const userSession = sessionStorage.getItem('userSession');
    const loginTimestamp = sessionStorage.getItem('loginTimestamp');
    
    if (userSession && loginTimestamp) {
      const currentTime = new Date().getTime();
      const timeoutDuration = parseInt(sessionStorage.getItem('sessionTimeout') || '1800000', 10);
      // 计算剩余超时时间
      const remainingTime = timeoutDuration - (currentTime - parseInt(loginTimestamp, 10));
      
      if (remainingTime > 0) {
        // 重置计时器为剩余时间(可以在服务里扩展一个initWithRemainingTime方法优化)
        this.sessionTimeoutService.initTimeout();
      } else {
        // 剩余时间不足,直接触发登出
        this.sessionTimeoutService.handleSessionExpiry();
      }
    }
  }
}

4. 可选:超时前弹窗提醒用户

如果需要像很多系统那样,在超时前几分钟弹出提示,询问用户是否要继续会话,可以在服务里加个预提醒逻辑:

// 在SessionTimeoutService里添加以下代码
private warningTimer: any;
private warningDuration = 300000; // 提前5分钟提醒

setTimeout() {
  // 先设置超时提醒
  this.warningTimer = setTimeout(() => {
    if (confirm('您的会话即将过期,是否继续保持登录?')) {
      this.resetTimeout();
    } else {
      this.handleSessionExpiry();
    }
  }, this.timeoutDuration - this.warningDuration);
  
  // 再设置最终超时计时器
  this.timeoutTimer = setTimeout(() => {
    this.handleSessionExpiry();
  }, this.timeoutDuration);
}

private clearAllTimers() {
  if (this.timeoutTimer) clearTimeout(this.timeoutTimer);
  if (this.warningTimer) clearTimeout(this.warningTimer);
}

注意事项

  • 敏感的session数据建议用sessionStorage存储,它会在浏览器关闭后自动清除,比localStorage更安全;
  • 如果项目里有HTTP拦截器,记得在会话过期后拦截后续API请求,避免无效请求发送到后端;
  • 在用户手动登出时,一定要调用服务的logout方法,确保所有计时器和存储数据都被清除。

内容的提问来源于stack exchange,提问作者Arturo Laos

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.27 06:45:00