【问题标题】:Guard on children routes守卫儿童路线
【发布时间】:2021-12-07 08:35:38
【问题描述】:

我知道这个主题经常在 StackOverflow 上得到处理。

我在 Stack 上查阅了几篇帖子,但建议的解决方案对我不起作用。

例如this one

我第一次尝试使用 Guards 限制对页面的访问,但它不适用于子页面。

我有一个卡车模块包含这样的孩子:

Truck
  |_ truck-list
  |_ truck-search
  |_ truck-menu
  |_ truck-details

我有一个卡车模块的路线文件:

RouterModule.forChild([
    {path: 'list', component: TruckListComponent, canActivate: [TruckGuard]},
    {path: 'search', component: TruckSearchComponent, canActivate: [TruckGuard]},
    {path: 'details/:id', component: TruckDetailsComponent},
    {path: 'menu', component: TruckMenuListComponent},
    {path: 'menu/:id', component: TruckMenuListComponent},
    {path: 'menu/add/:id', component: TruckMenuAddComponent},
    ])

还有一个应用路由模块:

const appRoutes: Routes = [
    { path: '', component: HomeComponent},
    { path: 'app-forbidden', component: ForbiddenComponent},
    { path: 'Home', component: HomeComponent},
    { path: 'About', component: AboutComponent},
    { path: 'forbidden', component: ForbiddenComponent},
    { path: 'Login', component: LoginComponent},
    { path: 'Logout', component: LoginComponent},
    { path: 'confirmation-commande/:message', component: ConfirmationCommandeComponent},
    { path: 'orders', component: OrderListComponent},
    { path: 'truck/search', component: TruckSearchComponent},
    { path: 'SignUp/customer', component: UseraccountCreateCustomerComponent},
    { path: 'SignUp/truck', component: UseraccountCreateTruckComponent},
    { path: 'useraccount', loadChildren: () => import('./useraccount/useraccount.module').then(u => u.UserAccountModule)},
    { path: 'truck', loadChildren: () => import('./truck/truck.module').then(t => t.TruckModule)},
    {path: 'location', component: TruckLocationComponent},
    { path: '500', component: InternalServerComponent },
    { path: '', redirectTo: '/home', pathMatch: 'full' }
  ];
...

我还创建了一个 Truck.guard.ts 文件来管理卡车模块的路线:

export class TruckGuard implements CanActivate, CanActivateChild {

  constructor(private authService: AuthService, private route: Router) {}
  canActivate(route: ActivatedRouteSnapshot, state: RouterStateSnapshot): boolean {
    let url = window.location.pathname;

    if((url == '/truck') && this.authService.isCustomer()){
      return true;
    }
    else{
      this.route.navigate(['app-forbidden']);
      return false;
    }
  }
 
  canActivateChild(childRoute: ActivatedRouteSnapshot, state: RouterStateSnapshot): boolean {
    let url = window.location.pathname;

    if((url == '/truck/list') && this.authService.isCustomer()){
      return true;
    }
    else if((url == '/truck/search') && this.authService.isCustomer()){
      return true;
    }
    else if((url == '/Login') && this.authService.isCustomer()){
      return true;
    }
    else{
      this.route.navigate(['app-forbidden']);
      return false;
    }
  }
}

唯一有效的路径是truck/list。他很好地被重定向到禁止页面。

其他的都不行。

我不明白为什么。但是我使用 canActivate 和 canActivateChild。

提前感谢您的帮助。

【问题讨论】:

标签: angular typescript guard


【解决方案1】:

最后解决办法是在app-module.ts中添加canActivateChild:

 { path: 'truck', loadChildren: () => import('./truck/truck.module').then(t => t.TruckModule), canActivateChild: [TruckGuard]},

并使用state: RouterStateSnapshot 代替window.location.pathname 在保护文件中测试url,如下所示:

 if((state.url == '/truck/list') && this.authService.isCustomer()){
      return true;
    }
    else if((state.url == '/truck/search') && this.authService.isCustomer()){
      return true;
    }
   else if((state.url == '/truck/menu') && this.authService.isCustomer()){
      return true;
    }
    else if((state.url == '/truck/menu/' + childRoute.params['id']) && this.authService.isCustomer()){
      return true;
    }
    else if((state.url == '/truck/details/' + childRoute.params['id']) && this.authService.isCustomer()){
      return true;
    }
    else if((state.url == '/Login') && this.authService.isCustomer()){
      return true;
    }
    else{
      this.route.navigate(['app-forbidden']);
      return false;
    }

【讨论】:

    【解决方案2】:

    你做错了几件事。

    1. 卡车/列表有效的原因是因为您在其上应用 canActivate 而不是此处的其余部分

       {path: 'list', component: TruckListComponent, canActivate: [TruckGuard]},
      

    在你的 canActivate 中,你只为卡车/列表提供服务

    canActivate(route: ActivatedRouteSnapshot, state: RouterStateSnapshot): boolean {
    let url = window.location.pathname;
    
    if((url == '/truck') && this.authService.isCustomer()){
      return true;
    }
    else{
      this.route.navigate(['app-forbidden']);
      return false;
    }
    

    }

    1. 其他人不工作的原因是因为您没有将 canActivateChild 应用到父模块。

    像这样向 appRoute 添加一个 canActivateChild

    const appRoutes: Routes = [
    { path: '', component: HomeComponent},
    { path: 'app-forbidden', component: ForbiddenComponent},
    { path: 'Home', component: HomeComponent},
    { path: 'About', component: AboutComponent},
    { path: 'forbidden', component: ForbiddenComponent},
    { path: 'Login', component: LoginComponent},
    { path: 'Logout', component: LoginComponent},
    { path: 'confirmation-commande/:message', component: ConfirmationCommandeComponent},
    { path: 'orders', component: OrderListComponent},
    { path: 'truck/search', component: TruckSearchComponent},
    { path: 'SignUp/customer', component: UseraccountCreateCustomerComponent},
    { path: 'SignUp/truck', component: UseraccountCreateTruckComponent},
    { path: 'useraccount', loadChildren: () => 
    import('./useraccount/useraccount.module').then(u => u.UserAccountModule)},
    // Truck module Your canActivateChild comes here    
    { path: 'truck', loadChildren: () => import('./truck/truck.module').then(t=> t.TruckModule)}, canActivateChild:TruckGuard // <<< HERE
    {path: 'location', component: TruckLocationComponent},
    { path: '500', component: InternalServerComponent },
    { path: '', redirectTo: '/home', pathMatch: 'full' }
    

    ];

    【讨论】:

    • 好吧,看起来更好,但是如何用参数测试 url?例如:` else if((url == '/truck/menu/:id') && this.authService.isCustomer()){ return true; }` 这不起作用。
    • 好的,我的问题有了答案。我必须用它来测试参数:else if((url == '/truck/menu/' + childRoute.params['id']) &amp;&amp; this.authService.isCustomer()){ return true; }
    • 另一个问题是,在一个页面上我有一个按钮可以重定向到另一个页面,但是当我在我的 Guard 页面中测试 url 时,它是当前 url 而不是询问的 url。
    • @Paintbox 你解决了你的第二个问题吗?另外,我建议您使用 switch 语句代替所有这些 if/else
    猜你喜欢
    • 2018-12-11
    • 2020-01-28
    • 1970-01-01
    • 2017-01-15
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多