Angular 从第一个选项卡注销时从第二个选项卡注销问题

Log out issue from second tab when log out from first tab in Angular

我正在使用 sessionStorage 来保存 accessToken。我的步骤如下:-

实际上它并没有让我从另一个选项卡中注销。

我添加了以下代码,但它没有按预期工作。

@HostListener('window:storage', ['$event'])
    onStorageChange(sv:StorageEvent) {       
      if(sv.storageArea == sessionStorage) 
      {
        let token = sessionStorage.getItem('accessToken');
        if(token == null || token == undefined)
            this.router.navigate(['/login']);
      }
    }

如果我做错了,请告诉我。 我目前在主页中使用此代码。位置对吗?

首先,您必须将此代码放入 app.component.ts 文件

其次写一个window事件

 window.addEventListener('storage', (event) => {
            if (event.storageArea == localStorage) {
                let token = localStorage.getItem('accessToken');
                if (token == undefined) {
                    // Perform logout
                    //Navigate to login/home
                    this.router.navigate(['/login']);
                }
            }
        });

我相信它应该可以正常工作

要在选项卡之间进行通信,您可以使用 localStorage 并仍然保留 sessionStorage 来存储您的敏感数据。

这是身份验证服务的一个小实现,它使用:

  • sessionStorage 存储您的用户数据(令牌或其他)
  • localStorage 与其他打开的标签进行通信。
  • rxjs 从服务触发事件

想法是您的应用程序侦听存储事件。然后,当您注销时,它会在 localStorage 中设置一个标志,其他打开的选项卡可以捕获该标志。

import { Injectable } from "@angular/core";
import { Subject, Observable } from "rxjs";

@Injectable({providedIn:'root'})

export class AuthenticationService{

  private eventSubject: Subject<boolean> = new Subject<boolean>();

  public readonly statusChanged$: Observable<boolean> = this.eventSubject.asObservable();

  private loggedIn = false;

  constructor()
  {
    window.onstorage = () => { //
    {
      let loggedIn = sessionStorage.getItem('accessToken') !== null;

      if(localStorage.getItem('signOut'))
      {
          loggedIn = false;
      }

      if(this.loggedIn !== loggedIn)//Don't trigger event if no change
      {
        this.loggedIn = loggedIn;
        this.eventSubject.next(loggedIn);
      }
    };
  }
}

  public logIn()
  {
    //Do your business to login and obtain a token before here...
    localStorage.removeItem('signOut');//clear flag in local storage
    sessionStorage.setItem('accessToken', 'token');//save token in session storage
  }

  public logOut()
  {
    localStorage.setItem('signOut', 'true'); //trigger flag
    sessionStorage.removeItem('accessToken'); //Remove token from session
  }
  public isLoggedIn()
  {
    return this.loggedIn;
  }
}

您可以只在您的组件中使用该服务

constructor(private authSvc:AuthenticationService)
{
    this.authSvc.statusChanged$.subscribe(isLoggedIn=>
    {
      //Do whatever you want

    });
}

这里是stackblitz demo

在需要登录的路由上实施 AuthGuard。在 Auth Guard 中添加您的登录检查逻辑,如果用户未登录则重定向到登录页面。

auth.guard.ts

import { Injectable } from '@angular/core';
import {Router,CanActivate,ActivatedRouteSnapshot,RouterStateSnapshot} 
from '@angular/router';

@Injectable({
  providedIn: 'root',
})
export class AuthGuard implements CanActivate {
  constructor(private router: Router) { }

  canActivate(route: ActivatedRouteSnapshot, state: RouterStateSnapshot) {
    let token = sessionStorage.getItem('accessToken');
    if(!token)
        this.router.navigate(['/login']);
        return false
    }
    return true;
  }
}

你的路由文件

const routes: Routes = [
  {
    path: '',
    component: YourComponent,
    canActivate: [AuthGuard],
}]

我希望这对您或任何正在寻找相同解决方案的人有用。谢谢