【问题标题】:How to make all non-child routes guarded?如何使所有非子路由受到保护?
【发布时间】:2019-07-31 06:21:53
【问题描述】:

我在 Angular 6 应用程序 (app.routing.ts) 中创建了一个路由模块。我在我的应用程序中添加了多个路由,但没有在任何地方使用child 指令作为我的路由(是的不好的做法,但是现在我在我的应用程序的另一部分添加了动态路由并且不想更改整个结构,因为这样做需要很长时间)。

我想知道是否有一种方法可以全局使用canActivate: [AuthGuardService](检查用户是否已登录)用于除根以外的所有路由。我检查了一个类似的答案here,但警卫似乎无法正常工作并且仍然加载页面。 (也许是因为我没有任何子路线)。

另外,我认为该方法也可能不是最好的方法,因为在这种情况下,Guard(消费层)能够知道哪个层正在使用它的方法(这不是 mvc 模式的最佳方法,授予我对路由模块所做的事情也不漂亮)。有没有办法以更清洁的方式实现这一目标?

app.routing.ts

export const routes: Routes = [
  {
    path: 'main',
    component: MainComponent,
    pathMatch: 'full'
  },
  {
    path: 'search/:id',
    component: GlobalSearchComponent
  },
  {
    path: '',
    canActivate: [AuthGuardService],
    component: LoginComponent,
  },
  {
    path: 'reset',
    component: ResetPasswordComponent
  },
  {
    path: 'forgot',
    component: ForgotPasswordComponent
  },
  {
    path: 'knowledge-base/create',
    component: KnowledgeBaseCreateComponent
  },
  {
    path: 'knowledge-base/detail/:id',
    component: KnowledgeBaseDetailComponent
  },
  {
    path: 'knowledge-base/edit/:id',
    component: KnowledgeBaseEditComponent
  },
  {
    path: 'projects/detail/:id',
    component: ProjectDetailComponent
  },
  {
    path: 'projects/create',
    component: ProjectCreateComponent
  },
  {
    path: '**',
    component: NotFoundComponent
  }
];

@NgModule({
  imports: [RouterModule.forRoot(routes)],
  exports: [RouterModule]
})
export class AppRoutingModule { }

authguard.service

import { Injectable } from '@angular/core';
import { Router, CanActivate, ActivatedRouteSnapshot, RouterStateSnapshot } from '@angular/router';
import { ToastrService } from 'ngx-toastr';
import { TranslatePipe } from 'src/app/pipes/translate/translate.pipe';

/**
* This injector provides the auth-guard service throughout the application.
*/
@Injectable({
  providedIn: 'root'
})

/**
* The auth guard service is used to prevent unauthenticated users from
* accessing restricted routes, it's used in app.routing.ts to protect the home
* page route
*/
export class AuthGuardService {
  /**
  * The constructor initializes the ToastrService & TranslatePipe in the component.
  */
  constructor(private toastr: ToastrService,
    private translate: TranslatePipe,
    private router: Router) { }
  /**
   * This method checks if the user is authorized to access a certain route.
   *
   * @param  route
   * @param  state
   * @return
   */
  canActivate(route: ActivatedRouteSnapshot, state: RouterStateSnapshot) {
    if (localStorage.getItem('jwtToken')) {
      return true;
    } else {
      if (this.router.url !== '/') {
        let error = this.translate.transform("generic[responses][error][401]");
        this.toastr.warning(error);
        this.router.navigate(['']);
      } else {
        return true;
      }
    }
  }
}

【问题讨论】:

    标签: angular typescript angular-router angular-router-guards


    【解决方案1】:

    实现它的干净方法是将它们包装在一条路线的children 中。你说你知道这一点,但你也提到它会导致你改变整个结构——事实并非如此。您可能想过使用loadChildren,这实际上会导致更大的变化。这是使用 children 包装 knowledge-base 路由的示例

      {
        path: 'knowledge-base',
        canActivate: [AuthGuardService],
        children: [
            {
              path: '',
              redirectTo: 'knowledge-base/create',
              pathMatch: 'full'
            },
            {
              path: 'create',
              component: KnowledgeBaseCreateComponent
            },
            {
              path: 'detail/:id',
              component: KnowledgeBaseDetailComponent
            },
            {
              path: 'edit/:id',
              component: KnowledgeBaseEditComponent
            }
        ]
      }
    

    这是你必须改变的一切,基本上只需将其包装在children 中。您也可以将此方法应用于其他路线。或者,如果您只想使用 RouterGuard 一次,您可以创建类似 path: 'main' 的内容,然后将所有内容都包装在那里

    【讨论】:

    • 其实这是一个有效的观点。此外,如果我不允许访问特定路由,则不会添加动态路由,因此无论如何它们都无法访问。简单地将所有内容封装在根的children 中确实解决了我的问题。谢谢!
    【解决方案2】:

    根据最佳实践,您应该分层组织路由并使用子路由嵌套子路由/组件。 Route Guards 也以同样的方式工作,这就是我们有 canActivateChild 守卫的原因。

    您仍然可以将路由重构为仅具有父子(嵌套)关系并使用 canActivateChild 保护。我认为改变这一点不会产生重大影响。如果你在模块中进行延迟加载和分离路由,那么它可能会发生很大的变化。

    canActivateChild(route: ActivatedRouteSnapshot, state: RouterStateSnapshot): 
        Observable<boolean> | Promise<boolean> | boolean {
           return this.canActivate(route, state);
    }
    
    { path: 'servers',  canActivateChild: [AuthGuard], component: ServersComponent,  children: [
          { path: ':id', component: ServerComponent, resolve: { server: ServerResolver } },
          { path: ':id/edit', component: EditServerComponent, canDeactivate: [canDeactivateGuard] }
    ]}
    
    
    

    【讨论】:

    • 同意,不幸的是,当我开始这个项目时,我几乎没有(如果有的话)关于如何正确使用角度路由的信息。当我开始了解这会产生什么影响时,我已经深入到我的应用程序中,并且不得不从那里即兴发挥
    猜你喜欢
    • 2020-02-26
    • 2022-11-16
    • 2021-05-23
    • 2021-04-06
    相关资源
    最近更新 更多