Angular 路由器:根据用户的角色导航到不同的路由
Posted
技术标签:
【中文标题】Angular 路由器:根据用户的角色导航到不同的路由【英文标题】:Angular router: navigating to different routes according to the user's role 【发布时间】:2021-07-12 21:26:35 【问题描述】:我正在编写一个具有以下结构的模拟电子商务应用程序:
应用程序 认证 登录页面 注册页面 auth-routing.module.tsconst 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 路由器:根据用户的角色导航到不同的路由的主要内容,如果未能解决你的问题,请参考以下文章
相同的 URL 路径,但根据用户角色加载不同的组件 - Angular
基于 JWT 身份验证和角色在 Express 中路由到多个 Angular 7 项目