17

从 Angular 文档上看,如果函数最终返回canActivate,您似乎只能使用canActivate守卫来允许继续执行路由。canActivatetrue

canActivate有没有办法说,“只有在班级评估为”时才继续这条路线false

例如,为了不允许登录用户访问登录页面,我尝试了这个,但它不起作用:

export const routes: Route[] = [
    { path: 'log-in', component: LoginComponent, canActivate: [ !UserLoggedInGuard ] },

我在控制台中收到此错误:

ERROR Error: Uncaught (in promise): Error: StaticInjectorError[false]: 
  StaticInjectorError[false]: 
    NullInjectorError: No provider for false!
Error: StaticInjectorError[false]: 
  StaticInjectorError[false]: 
    NullInjectorError: No provider for false!
4

3 回答 3

20

您的问题中有趣的是公式:

有没有办法说,“只有在canActivate 类评估为 false时才继续这条路线 ”?

以及您如何表达“直观”的解决方案:

{ path: 'log-in', component: LoginComponent, canActivate: [ !UserLoggedInGuard ] },

这基本上说,你需要negate的结果UserLoggedInGuard@canActivate

让我们考虑以下实现UserLoggedInGuard

@Injectable()
export class UserLoggedInGuard implements CanActivate {
   constructor(private _authService: AuthService) {}

   canActivate(route: ActivatedRouteSnapshot, state: RouterStateSnapshot): boolean {
        return this._authService.isLoggedIn();
    }
} 

接下来,让我们看看@Mike 提出的解决方案

@Injectable()
export class NegateUserLoggedInGuard implements CanActivate {    
    constructor(private _authService: AuthService) {}

   canActivate(route: ActivatedRouteSnapshot, state: RouterStateSnapshot): boolean {
        return !this._authService.isLoggedIn();
    }
}

现在,该方法还可以,但与UserLoggedInGuard. 如果由于某种原因执行UserLoggedInGuard@canActivate更改,NegateUserLoggedInGuard将会中断。

我们怎样才能避免呢?简单,滥用依赖注入:

@Injectable()
export class NegateUserLoggedInGuard implements CanActivate {    
  constructor(private _userLoggedInGuard: UserLoggedInGuard) {}

  canActivate(route: ActivatedRouteSnapshot, state: RouterStateSnapshot): boolean {
     return !this._userLoggedInGuard.canActivate(route,state);
  }
}

现在这正是你所表达的

canActivate: [ !UserLoggedInGuard ]

最好的部分:

  • 它没有与内部实现紧密耦合UserLoggedInGuard
  • 可以扩展来操作多个Guard类的结果
于 2018-01-14T15:48:49.393 回答
3

我有一个类似的问题 - 想要制作一个只有在未经身份验证时才能访问的登录页面,并且只有在您通过身份验证时才能访问仪表板(并自动将用户重定向到适当的登录页面)。我通过使警卫本身登录+路由敏感来解决它:

路线:

const appRoutes: Routes = [
  { path: 'login', component: LoginComponent, canActivate: [AuthGuard] },
  { path: 'dashboard', component: DashboardComponent, canActivate: [AuthGuard] },

守卫:

export class AuthGuard implements CanActivate {

  private login: UrlTree;
  private dash: UrlTree;

  constructor(private authSvc: AuthenticationService, private router: Router ) {
    this.login = this.router.parseUrl('login');
    this.dash = this.router.parseUrl('dashboard');
  }

  canActivate(route: ActivatedRouteSnapshot, state: RouterStateSnapshot): boolean | UrlTree {
    if (this.authSvc.isSignedIn()) {
      if (route.routeConfig.path === 'login') {
        return this.dash;
      } else {
        return true;
      }
    } else {
      if (route.routeConfig.path === 'login') {
        return true;
      } else {
        return this.login;
      }
    }
  }
}
于 2019-10-05T22:39:40.087 回答
2

考虑到您的问题,一种解决方案可能是实现一个反向执行逻辑的路由保护。

import { MyService } from "./myservice.service";
import { CanActivate, RouterStateSnapshot, ActivatedRouteSnapshot } from "@angular/router";
import { Injectable } from "@angular/core";

@Injectable()
export class MyGuard implements CanActivate {

    constructor(private myService: MyService) {}

    canActivate(route: ActivatedRouteSnapshot, state: RouterStateSnapshot) {
        return this.myService.isNotLoggedIn(); //if user not logged in this is true
    }
}
于 2018-01-14T01:02:37.540 回答