1

所以,这就是我的 AuthGuard 的样子:

canLoad(route: Route) {
    return this.store.select(fromRoot.getIsAuth).pipe(take(1));
}

我从 app.component 检查身份验证信息并简单地返回一个 Observable 布尔值。

我不想订阅这个来重新路由,我不想在 AuthGuard 中使用 router.navigate,所以我想保持它是一个简单的 Guard。

有没有办法在路由模块内部重新路由,如果 AuthGuard 返回 false,它只是路由到备用路径?

4

2 回答 2

2

据我所知,您必须在警卫中进行导航。没有办法配置路由器做你想做的事。但是你不需要订阅。您可以使用点击进行导航。

canLoad(route: Route) {
    return this.store.select(fromRoot.getIsAuth)
        .pipe(
            take(1),
            tap(loggedIn => {
                if (!loggedIn) {
                    this.router.navigate(['/login']);
                }
            })
        );
}
于 2018-09-07T12:20:36.940 回答
0

TLDR;如果您直接在内部导航,OnLoad您将收到一个 NavigationCancel 事件,其中包含有关 ID 不匹配的消息(我讨厌这个错误!)。你可以像这样避免它:

this.routerEvents.navigationCancel$.pipe(take(1)).subscribe(() =>
{           
      this.router.navigateByUrl(result); 
});

return false;

我不确定大多数人何时使用canLoadvs.canActivate但我的具体情况(和解决方案)如下:

  • AuthGuard我有一个从我的服务内部显示的登录对话框。显示AuthGuard对话框,但在用户尝试登录之前不会返回真/假。
  • 如果登录失败并且需要将用户重定向到特定页面(例如支持页面),则服务AuthGuard返回UrlTree
  • 我的“/account”路线是延迟加载的,可能需要几秒钟才能加载
  • 我希望在用户单击“帐户”时立即出现登录对话框,因此添加CanLoad
  • 因此,我所做的是将相同的逻辑放入我的canLoad处理程序中。这意味着canLoad如果它首先被击中,它也会显示一个对话框。
  • 我让我的canActivate警卫运行完全相同的逻辑(别担心 - 你永远不会看到两个对话框)

对于这种情况,我发现最简单的方法是canLoad

canLoad(route: Route, segments: UrlSegment[])
   {
       const currentNavigation = this.router.getCurrentNavigation();
       const isInitialNavigation = !currentNavigation.previousNavigation;

       if (isInitialNavigation)
       {
           return true;   // always allow load for first navigation (avoids other complications)
       }
       else {

           // returns Observable<boolean | UrlTree> 
           return showLoginDialog().pipe(map(result => {

               if (typeof result === 'boolean') {
                  return result;
               }
               else {
                     // we have a URL tree
                    // wait for the expected NavigationCancel event and then navigate
                    this.routerEvents.navigationCancel$.pipe(take(1)).subscribe(() =>
                    {           
                       this.router.navigateByUrl(result); 
                    });
                   return false;
                }
           });;    
       }
}

我也有一个根提供的RouterEvents服务,我在其中定义

  navigationCancel$ = this.router.events.pipe(filter((e): e is NavigationCancel => e instanceof NavigationCancel));

注意:请注意您是否选择不包括isInitialNavigation支票。如果您的重定向试图重定向到主页,那么它将不起作用,因为路由器认为您已经在那里。/redirect_home您可以使用仅重定向到主页的路由来解决此问题- 或更改onSameURLNavigation设置。

于 2020-02-19T01:13:33.777 回答