在访问最终路由到 url 时加载模块之前加载权限
Load permissions before loading module when is accesed final route into url
好的,我有一条路线:site/dashboards/orders
{
path: 'dashboards',
loadChildren: () => import('./dashboards/dashboards.module').then(m => m.DashboardsModule),
canActivate: [AuthGuard, NgxPermissionsGuard],
data: {
permissions: {
only: ['admin', 'dashboards'],
redirectTo: 'homepage'
}
}
}
在我的应用程序组件中,我检查用户是否已通过身份验证,如果是,则从 api 获取角色并使用 NgxPermissions 模块
加载权限
app.component.ts(在构造函数中):
constructor(private services) {
this.checkAuth();
}
checkAuth() {
apiService.checkAuth().subscribe((value: boolean) => {
if (value) {
// get roles with another api call
apiService.getRoles().subscribe(roles => {
this.permissionsService.loadPermissions(roles);
});
}
});
}
我知道这不是在另一个订阅中订阅的最佳方式,但现在这并不重要。
如果我从第一页访问该站点,则问题不存在,因为:
转到site/homepage => checkAuth() 已执行并且有足够的时间
获得 api 结果 => 加载角色
导航到 dashboards/orders => 角色已经从
上一步(如果我的导航速度不是太快)和路由转到
路径 'dashboards' 并仅使用 ['admin' 权限检查数据,
'dashboards'],这将允许我访问路线,因为
存在角色。
但是,如果我尝试直接访问 site/dashboards/orders:
- app.component.ts 是 Angular 中第一个加载的组件,所以会调用
检查授权()方法。但是因为这是一个可观察的,将传递给
下一步操作(检查路由数据权限),然后再完成。
因为没有加载角色,应用程序会将我重定向到 'homepage'.
如何在访问路由和验证权限之前等待加载角色?
我只需要获取角色一次(在第一次访问应用程序时),而不是为每个路由模块获取角色。可以在路由模块中监听 observables 吗?
不久,我需要在路由之前加载角色。
谢谢
我找到了一个解决方案,我不知道是否是最好的,但它的工作原理:
放弃 NgxPermissionsGuard 并创建另一个实现 CanActivate 的守卫 "PermissionsGuard" 并发送 roles 和 redirectTo 作为两个守卫的参数.
路由:
{
path: 'dashboards',
loadChildren: () => import('./dashboards/dashboards.module').then(m => m.DashboardsModule),
canActivate: [AuthGuard, PermissionsGuard],
data: {
roles: ['admin', 'dashboards'],
redirectTo: 'homepage'
}
}
PermissionsGuard.ts:
export class PermissionsGuard implements CanActivate {
canActivate(
next: ActivatedRouteSnapshot,
state: RouterStateSnapshot): Observable<boolean> | Promise<boolean> | boolean {
const routeRoles = next.data.roles as Array<string>;
const redirectTo = next.data.redirectTo;
const userName = localStorage.getItem('userName');
return this.getRoles(userName, routeRoles, redirectTo);
}
getRoles(userName: string, routeRoles: string[], redirectTo: string) {
let userRoles = [];
const roles = this.permissionsService.getPermissions();
for (const key in roles) {
userRoles.push(key);
}
if (userRoles.length > 0) {
return this.isInRole(userRoles, routeRoles, redirectTo);
} else {
// api call, get user roles
return this.isInRole(apiResult, routeRoles, redirectTo);
}
}
isInRole(userRoles: string[], routeRoles: string[], redirectTo: string) {
// let canAccessRoute = false;
// check if routeRoles contain any element of userRoles
if (canAccessRoute) {
return true;
} else {
this.router.navigateByUrl(redirectTo);
}
}
}
两个守卫(AuthGuard 和 PermissionsGuard)都需要 return true 让用户访问路由。一些数据是承诺的结果,因此需要使用 returning 方法。
好的,我有一条路线:site/dashboards/orders
{
path: 'dashboards',
loadChildren: () => import('./dashboards/dashboards.module').then(m => m.DashboardsModule),
canActivate: [AuthGuard, NgxPermissionsGuard],
data: {
permissions: {
only: ['admin', 'dashboards'],
redirectTo: 'homepage'
}
}
}
在我的应用程序组件中,我检查用户是否已通过身份验证,如果是,则从 api 获取角色并使用 NgxPermissions 模块
加载权限app.component.ts(在构造函数中):
constructor(private services) {
this.checkAuth();
}
checkAuth() {
apiService.checkAuth().subscribe((value: boolean) => {
if (value) {
// get roles with another api call
apiService.getRoles().subscribe(roles => {
this.permissionsService.loadPermissions(roles);
});
}
});
}
我知道这不是在另一个订阅中订阅的最佳方式,但现在这并不重要。
如果我从第一页访问该站点,则问题不存在,因为:
转到site/homepage => checkAuth() 已执行并且有足够的时间 获得 api 结果 => 加载角色
导航到 dashboards/orders => 角色已经从 上一步(如果我的导航速度不是太快)和路由转到 路径 'dashboards' 并仅使用 ['admin' 权限检查数据, 'dashboards'],这将允许我访问路线,因为 存在角色。
但是,如果我尝试直接访问 site/dashboards/orders:
- app.component.ts 是 Angular 中第一个加载的组件,所以会调用 检查授权()方法。但是因为这是一个可观察的,将传递给 下一步操作(检查路由数据权限),然后再完成。 因为没有加载角色,应用程序会将我重定向到 'homepage'.
如何在访问路由和验证权限之前等待加载角色?
我只需要获取角色一次(在第一次访问应用程序时),而不是为每个路由模块获取角色。可以在路由模块中监听 observables 吗?
不久,我需要在路由之前加载角色。
谢谢
我找到了一个解决方案,我不知道是否是最好的,但它的工作原理:
放弃 NgxPermissionsGuard 并创建另一个实现 CanActivate 的守卫 "PermissionsGuard" 并发送 roles 和 redirectTo 作为两个守卫的参数.
路由:
{
path: 'dashboards',
loadChildren: () => import('./dashboards/dashboards.module').then(m => m.DashboardsModule),
canActivate: [AuthGuard, PermissionsGuard],
data: {
roles: ['admin', 'dashboards'],
redirectTo: 'homepage'
}
}
PermissionsGuard.ts:
export class PermissionsGuard implements CanActivate {
canActivate(
next: ActivatedRouteSnapshot,
state: RouterStateSnapshot): Observable<boolean> | Promise<boolean> | boolean {
const routeRoles = next.data.roles as Array<string>;
const redirectTo = next.data.redirectTo;
const userName = localStorage.getItem('userName');
return this.getRoles(userName, routeRoles, redirectTo);
}
getRoles(userName: string, routeRoles: string[], redirectTo: string) {
let userRoles = [];
const roles = this.permissionsService.getPermissions();
for (const key in roles) {
userRoles.push(key);
}
if (userRoles.length > 0) {
return this.isInRole(userRoles, routeRoles, redirectTo);
} else {
// api call, get user roles
return this.isInRole(apiResult, routeRoles, redirectTo);
}
}
isInRole(userRoles: string[], routeRoles: string[], redirectTo: string) {
// let canAccessRoute = false;
// check if routeRoles contain any element of userRoles
if (canAccessRoute) {
return true;
} else {
this.router.navigateByUrl(redirectTo);
}
}
}
两个守卫(AuthGuard 和 PermissionsGuard)都需要 return true 让用户访问路由。一些数据是承诺的结果,因此需要使用 returning 方法。