Angular路由器激活了错误的路由保护

Angular router activates wrong route guard

我遇到了 Angular 似乎没有多大意义的路由问题。通过以下设置,会出现此结果...

然而...

我很难理解为什么 auth guard 运行宁 /activate 路由不是仪表板布局的子路由。

应用程序路由

 {
    path: '',
    component: DashboardLayoutComponent,
    canActivate: [AuthGuard],
    canActivateChild: [DashboardGuard],
    children: [
      {
        path: 'schedule',
        loadChildren: () =>
          import('@libs/schedule').then(
            i => i.ScheduleModule
          ),
        data: {
          breadcrumb: 'Schedule'
        }
      },
      // Other feature modules omitted
      {
        path: '',
        redirectTo: '/schedule',
        pathMatch: 'full'
      }
    ]
  }

账户路由

  { path: 'login', component: LoginComponent },
  { path: 'activate', component: ActivateComponent }

Auth Guard

@Injectable()
export class AuthGuard implements CanActivate {
  constructor(
    private jwtService: JwtService,
    private router: Router,
    private accountService: accountService
  ) { }

  canActivate(
    route: ActivatedRouteSnapshot,
    state: RouterStateSnapshot
  ): Observable<boolean> | Promise<boolean> | boolean {

    console.log('Auth Guard Start'); // <-- This appears in console

    return this.jwtService.getToken().pipe(
      map(token => {
        if (!token) {
          this.router.navigate(['/login']);
          return false;
        }
        // Attempt to populate the user using the token.
        this.accountService.populate();
        return true;
      }),
      take(1)
    );
  }
}

应用模块

@NgModule({
  declarations: [AppComponent, DashboardLayoutComponent],
  imports: [
    // .. other modules omitted
    AccountModule,
    AppRoutingModule
  ],
  providers: [AuthGuard, DashboardGuard],
  bootstrap: [AppComponent]
})
export class AppModule { }

附加信息

这仅在 运行 处于生产模式时发生。

Augury 报告说 /login/activate 都是 / 路线的兄弟姐妹。 https://imgur.com/a/CJyKu8C

@angular/core: 8.2.6

@angular/router: 8.2.6

其实我认为,你的问题的线索如下:

您首先为会计模块添加路由,当然在该模块中您将它们标记为 forChild。 然后,您添加了主 AppModuleRouts。 在您的应用程序被编译并且 运行 - etire RouterTree 包括所有可能的路径之后。因此,来自 AccountModule 的路由实际上成为了子路由。 因此,就您在空路由上应用 canActivate: [AuthGuard] 而言——最一般的可能是——它每次都会触发。

这个问题实际上是由我定义初始状态的 ngrx-router 实现引起的。

最初的初始状态是按照此处建议的以下方式设置的 - https://github.com/ngrx/platform/issues/835#issuecomment-369592809

export const routerInitialState: fromRouter.RouterReducerState<RouterStateUrl> = {
  state: {
    url: window.location.pathname,
    queryParams: getQueryParams(window.location.search.substring(1)),
    params: {}
  },
  navigationId: 0
}

这不适用于生产版本。例如,直接导航到 /activate 之类的路线会导致路由器状态与 angular 路由器状态之间存在差异,从而取消导航。

top设置初始路由器状态的正确方法如下...

export const routerInitialState: fromRouter.RouterReducerState<RouterStateUrl> = {
  state: {
    url: '/',
    queryParams: {},
    params: {}
  },
  navigationId: 0
}

app-routing.module 中使用 initialNavigation: 'enabled',路由器状态会在尽可能早的时间点更新,并与 angular 路由器同步。