Angular 路由器:根据用户的角色导航到不同的路由

Posted

技术标签:

【中文标题】Angular 路由器:根据用户的角色导航到不同的路由【英文标题】:Angular router: navigating to different routes according to the user's role 【发布时间】:2021-07-12 21:26:35 【问题描述】:

我正在编写一个具有以下结构的模拟电子商务应用程序:

应用程序 认证 登录页面 注册页面 auth-routing.module.ts
const routes: Routes = [
  
    path: 'signup',
    component: SignUpPage,
  ,
  
    path: 'signin',
    component: SignInPage,
  ,
];
auth.module.ts 管理员 根页面 admin-routing.module.ts
const routes: Routes = [
  
    path: 'admin',
    component: RootPage,
    children: [
      // ...                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                   
    ],
  ,
];
admin.modules.ts 客户 根页面 目录页 结帐页面 感谢页面 customer-routing.module.ts
const routes: Routes = [
  
    path: 'customer',
    component: RootPage,
    children: [
       path: 'catalog/:categoryId', component: CatalogPage ,
       path: 'checkout', component: CheckOutPage ,
       path: 'thankyou', component: ThankYouPage ,
    ],
  ,
];
customer.module.ts 页面未找到 app-routing.module.ts
const routes: Routes = [
   path: '**', component: NotFoundPage ,
];
app.module.ts app.component.html app.component.css

基本的工作流程应该如下:

    用户导航到根路径/。 应用程序检测到他们没有登录,因此将他们重定向到/signin。 他们输入凭据并按登录。 如果认证成功,
      如果用户是管理员,他们会被重定向到/admin
        admin-router.module.ts 将它们重定向到 /admin 的某个子路径。
      如果用户是客户,他们会被重定向到/customer
        customer-router.module.ts 将他们重定向到 /customer/catalog/<default category ID>。 他们将一些产品放入购物车,然后前往/customer/checkout。 他们下订单并被重定向到/customer/thankyou

我不确定如何在成功登录后完成重定向。显然它必须分两个阶段完成:首先到一些公共路径,例如/,然后到/customer/admin,具体取决于用户的角色。第二阶段可能需要app-routing.module.ts处理,可能需要使用警卫,但我不确定具体该怎么做。

编辑 (2021-04-20)

问题可以总结如下:

我需要一种方法(最好是声明性的)将应用程序从 / 重定向到以下路径之一,具体取决于其状态:

State Path
Logged out /auth
Logged in as a customer /customer
Logged in as an admin /admin

【问题讨论】:

对于第二部分,我认为您最好使用resolver,它将返回您需要的数据。 也看看这里***.com/a/38096468/5107490 在用户通过身份验证后,为什么不直接使用 router.navigate 到 /admin 或 /customer? @c_froehlich 显然这会起作用,但它会在登录页面和应用程序的其余部分之间产生不良耦合。从理论上讲:无论如何,我需要将已登录用户的请求重定向到/customer/admin,因此对于用户刚刚完成的情况,没有理由单独实现此重定向已登录。 @RonInbar 我明白了。通常我定义一个发射器,只要用户“状态”发生变化(登录、注销),它就会触发下一个事件。 “InitialPageService”可以订阅此事件并进行重定向。这样它就不会绑定到特定的路线。 【参考方案1】:

您可以创建一些虚拟组件并使用处理正确导航的守卫来保护它。像这样的:

[
  
    path: 'loggedin',
    component: DummyComponent,
    canActivate: [HandleLoginGuard]
  ,
  
    path: 'admin',
    component: AdminComponent,
  ,
  
    path: 'customer',
    component: CustomerComponent,
  
]


@Injectable()
class HandleLoginGuard implements CanActivate 
  canActivate(
    route: ActivatedRouteSnapshot,
    state: RouterStateSnapshot
  ) 
    if(isAdmin())
        route.navigate(/admin);
    else
        route.navigate(/customer);
    
    return false;
  

这样你可以把逻辑放在一个守卫而不是登录组件中。

【讨论】:

实际上不需要虚拟组件。您可以使用空的children 数组定义无组件路由。【参考方案2】:

我最终做的是:

// app-routing.module.ts

const routes: Routes = [
  
    path: '',
    canActivate: [AuthorizationGuard],
    children: [],
  ,
   path: '**', component: NotFoundPage ,
];
// authorization.guard.ts

@Injectable(
  providedIn: 'root',
)
export class AuthorizationGuard implements CanActivate 

  constructor(private router: Router, private authService: AuthService) 

  canActivate(
    route: ActivatedRouteSnapshot,
    state: RouterStateSnapshot
  ): UrlTree 
    const user = this.authService.getLoggedInUser();
    return (
      (user?.role === 'admin' && this.router.parseUrl('/admin')) ||
      (user?.role === 'customer' && this.router.parseUrl('/customer')) ||
      this.router.parseUrl('/auth')
    );
  


【讨论】:

那么基本上,你按照我的建议做了? @RobinDijkhof 基本上是的,但是有一些细微的差别。一方面,/admin/customer 路由在不同的模块中定义。另外,正如我在之前的评论中指出的那样,我没有使用虚拟组件。 我没有看到这里定义的 /admin/customer 的路线,所以我认为它在技术上不能回答你的问题。另外——你现在的后卫有不止一项职责,最好是两名后卫。当您在app-routing.module.ts 中看到类似AdminGuard 的内容时,您会确切地知道它在做什么,而不是类似AuthenticationAndRouteBasedAuthorizationGuard。无论如何,很高兴您找到了不需要虚拟组件的解决方案。 @Dean 请参阅原始问题。 /admin/customer 路由在各自的模块中定义。

以上是关于Angular 路由器:根据用户的角色导航到不同的路由的主要内容,如果未能解决你的问题,请参考以下文章

个人技术博客——Angular路由

相同的 URL 路径,但根据用户角色加载不同的组件 - Angular

Angular 5:用于导航到相同路线但参数不同的路线动画

基于 JWT 身份验证和角色在 Express 中路由到多个 Angular 7 项目

Angular rc3 路由器 - 使用不同参数导航到同一页面

角度导航到具有不同参数的相同路线