你如何使用Angular的canActivate来否定守卫的结果?

时间:2018-01-10 22:22:12

标签: angular typescript angular-routing canactivate angular-guards

canActivate上的{p> From the Angular documentation,如果canActivate函数最终返回canActivate,您似乎只能使用true警卫来继续进行路由。< / p>

有没有办法说,“如果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!

3 个答案:

答案 0 :(得分:5)

你问题中有趣的是配方:

  

有没有办法说,&#34;只有这样才能进入这条路线    canActivate类评估为false &#34; ?

你是如何表达&#34;直观的&#34;溶液:

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

基本上说,您需要negate <{1}}

的结果

让我们考虑UserLoggedInGuard@canActivate的以下实现:

UserLoggedInGuard

接下来,让我们看一下@Mike

提出的解决方案
@Injectable()
export class UserLoggedInGuard implements CanActivate {
   constructor(private _authService: AuthService) {}

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

现在,方法还可以,但与@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
  • 的结果

答案 1 :(得分: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
    }
}

答案 2 :(得分:0)

我有一个类似的问题-想要使登录页面仅在未经身份验证的情况下才可以访问,而仪表板仅在您经过身份验证时才可以访问(并自动将用户重定向到适当的页面)。我通过使防护本身登录+路由敏感来解决此问题:

路线:

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;
      }
    }
  }
}