首页 > 解决方案 > Angular Routing 演示:如果注销则自动远离保护区(重新启动 canActivate 守卫)

问题描述

请参阅有关路由的官方 Angular 文档:https ://angular.io/guide/router

及其演示:https ://stackblitz.com/angular/pbqlrdpbpvx

该演示演示了一个管理部分,只有在 auth 服务状态isloggedIn返回 true 时才能访问该部分。该部分受 canActivate auth-guard 保护。

从本质上讲,canActivate 守卫只会在您尝试访问页面时触发一次。如果您的身份验证服务状态ìsloggedIn返回 false,则正确地将您路由到登录过程。

但是,如果我的身份验证服务状态的值发生变化,我需要我的 canActivate 警卫每次触发ìsloggedIn,以确保如果身份验证状态本身变为假(即,如果我稍后使用到期日期或其他内容),以让用户自动离开受保护的部分。如果值突然变为 false,他将不会留在保护区页面上。

通过在顶部导航中添加一个简单的注销按钮来重现的步骤:

  1. 扩展演示(https://stackblitz.com/angular/pbqlrdpbpvx),顶部有注销按钮:

app.component.ts:

import { Component } from '@angular/core';
import { RouterOutlet } from '@angular/router';
import { slideInAnimation } from './animations';
import { AuthService } from './auth/auth.service';

@Component({
  selector: 'app-root',
  templateUrl: 'app.component.html',
  styleUrls: ['app.component.css'],
  animations: [ slideInAnimation ]
})
export class AppComponent {  
  constructor(public authService: AuthService) {}

  getAnimationData(outlet: RouterOutlet) {
    return outlet && outlet.activatedRouteData && outlet.activatedRouteData['animation'];
  }

  logout() {
    this.authService.logout();
  }
}

app.component.html:

<h1 class="title">Angular Router</h1>
<nav>
  <a routerLink="/crisis-center" routerLinkActive="active">Crisis Center</a>
  <a routerLink="/superheroes" routerLinkActive="active">Heroes</a>
  <a routerLink="/admin" routerLinkActive="active">Admin</a>
  <a routerLink="/login" routerLinkActive="active">Login</a>
  <a (click)="logout()" *ngIf="authService.isLoggedIn">Click To Logout</a>
  <a [routerLink]="[{ outlets: { popup: ['compose'] } }]">Contact</a>
</nav>
<div [@routeAnimation]="getAnimationData(routerOutlet)">
  <router-outlet #routerOutlet="outlet"></router-outlet>
</div>
<router-outlet name="popup"></router-outlet>
  1. 单击登录按钮并登录-您将被路由到管理部分,顶部导航上的注销按钮将显示。

  2. 单击注销按钮,查看视图保持不变。您仍在管理部分。

预期行为:

如果 auth 服务的 isLoggedIn 状态变为 false,用户将自动被重定向到登录页面。因此, anActivate 守卫应该在值更改时自动触发。

当前行为的原因:

auth guard 的 canActivate 决定你是否可以访问页面,当你进入页面时,它只在开始时检查一次。

当前解决方案:

通过对登录部分的路由调用扩展注销按钮的单击功能。然而,这并不涵盖所有用例。

提前致谢。

标签: angularangular-routingangular9

解决方案


您是否尝试过从 Auth Guard 调用 Observable,

constructor(private authService:AuthService, private router:Router) { }

    canActivate(next:ActivatedRouteSnapshot, state:RouterStateSnapshot) {
        return this.authService.isLoggedIn().map( v => {
            if (v) {
                return true;
            }
        }).catch(() => {
            this.router.navigate(['/login']);
            return Observable.of(false);
        });
    } 

推荐阅读