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

Angular 11实现单标签页登出时所有标签页同步登出(Cookie存Token)

Angular 11 多标签页同步登出实现方案

由于Cookie的变更不会触发浏览器的storage事件,我们需要结合localStorage传递登出信号,配合Cookie清理逻辑实现多标签页同步登出,具体实现步骤如下:

1. 改造登出逻辑

在登出方法中,除了清除Token对应的Cookie,还要在localStorage中写入一个登出标识,触发其他标签页的storage事件:

// auth.service.ts
import { Injectable } from '@angular/core';
import { CookieService } from 'ngx-cookie-service'; // 假设使用ngx-cookie-service操作Cookie

@Injectable({ providedIn: 'root' })
export class AuthService {
  constructor(private cookieService: CookieService) {}

  logout(): void {
    // 清除Token Cookie(注意path/domain要和设置时一致)
    this.cookieService.delete('token', '/');
    // 写入登出触发信号,触发跨标签页storage事件
    localStorage.setItem('app-logout-trigger', Date.now().toString());
    // 立即移除标记,避免残留影响后续操作
    setTimeout(() => localStorage.removeItem('app-logout-trigger'), 100);
    // 当前标签页跳转到登录页
    window.location.href = '/login';
  }
}

2. 全局监听Storage事件

通过根组件或全局服务监听storage事件,检测到登出信号时执行本地登出逻辑:

方式一:根组件中直接监听

// app.component.ts
import { Component, HostListener, OnDestroy } from '@angular/core';
import { CookieService } from 'ngx-cookie-service';

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

  @HostListener('window:storage', ['$event'])
  onStorageChange(event: StorageEvent): void {
    // 检测是否是我们定义的登出触发信号
    if (event.key === 'app-logout-trigger') {
      this.handleCrossTabLogout();
    }
  }

  private handleCrossTabLogout(): void {
    // 清除当前标签页的Token Cookie
    if (this.cookieService.check('token')) {
      this.cookieService.delete('token', '/');
    }
    // 避免重复跳转,仅当前不在登录页时跳转
    if (window.location.pathname !== '/login') {
      window.location.href = '/login';
    }
  }

  ngOnDestroy(): void {
    // HostListener会自动移除监听,无需手动处理
  }
}

方式二:全局服务监听

如果需要更灵活的逻辑拆分,可以创建全局服务:

// cross-tab-logout.service.ts
import { Injectable, OnDestroy } from '@angular/core';
import { CookieService } from 'ngx-cookie-service';

@Injectable({ providedIn: 'root' })
export class CrossTabLogoutService implements OnDestroy {
  private storageListener: EventListener;

  constructor(private cookieService: CookieService) {
    this.storageListener = (event: StorageEvent) => {
      if (event.key === 'app-logout-trigger') {
        this.handleLogout();
      }
    };
    window.addEventListener('storage', this.storageListener);
  }

  private handleLogout(): void {
    if (this.cookieService.check('token')) {
      this.cookieService.delete('token', '/');
    }
    if (window.location.pathname !== '/login') {
      window.location.href = '/login';
    }
  }

  ngOnDestroy(): void {
    // 组件销毁时移除监听,避免内存泄漏
    window.removeEventListener('storage', this.storageListener);
  }
}

然后在根组件中注入该服务,确保监听全局生效:

// app.component.ts
import { Component } from '@angular/core';
import { CrossTabLogoutService } from './cross-tab-logout.service';

@Component({
  selector: 'app-root',
  templateUrl: './app.component.html'
})
export class AppComponent {
  constructor(private crossTabLogoutService: CrossTabLogoutService) {}
}

3. 关键注意事项

  • storage事件仅在同源的其他标签页触发,当前触发变更的标签页不会收到事件,所以当前标签页的登出逻辑需要直接执行
  • 建议给localStorage的key加项目前缀,避免和其他业务逻辑冲突
  • 清理Cookie时要保证path和domain参数与设置时一致,否则无法正确清除
  • 若使用sessionStorage替代localStorage,则仅在同一会话的标签页中生效,可根据业务需求选择

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.06 01:31:17