【问题标题】:Angular router: navigating to different routes according to the user's roleAngular 路由器:根据用户的角色导航到不同的路由
【发布时间】: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

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

  1. 用户导航到根路径/
  2. 应用程序检测到他们没有登录,因此将他们重定向到/signin
  3. 他们输入凭据并按登录
  4. 如果认证成功,
    1. 如果用户是管理员,他们会被重定向到/admin
      1. admin-router.module.ts 将它们重定向到 /admin 的某个子路径。
    2. 如果用户是客户,他们会被重定向到/customer
      1. customer-router.module.ts 将他们重定向到 /customer/catalog/<default category ID>
      2. 他们将一些产品放入购物车,然后前往/customer/checkout
      3. 他们下订单并被重定向到/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,它将返回您需要的数据。
  • 在用户通过身份验证后,为什么不直接使用 router.navigate 到 /admin 或 /customer?
  • @c_froehlich 显然这会起作用,但它会在登录页面和应用程序的其余部分之间产生不良耦合。从理论上讲:无论如何,我需要将已登录用户的请求重定向到/customer/admin,因此对于用户刚刚完成的情况,没有理由单独实现此重定向已登录。
  • @RonInbar 我明白了。通常我定义一个发射器,只要用户“状态”发生变化(登录、注销),它就会触发下一个事件。 “InitialPageService”可以订阅此事件并进行重定向。这样它就不会绑定到特定的路线。

标签: angular authentication angular-routing user-roles angular-guards


【解决方案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 路由在各自的模块中定义。
猜你喜欢
  • 1970-01-01
  • 2020-10-27
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2021-03-17
  • 2019-09-27
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多