Angular之ngx-permissions的路由使用

Angular之ngx-permissions的路由使用

介绍

现在,你准备开始与控制访问应用程序的状态工作。为了限制任何状态ngx-permission需要依靠 Angular Route 数据属性,通过permissions间接控制认证配置。

Permissions对象接受以下属性:

属性 接受值
only String|Array|Function
except String|Array|Function
redirectTo String

only和except属性

  1. only属性

    • 用于明确定义权限或角色被允许访问的状态
    • 使用String时,包含单一许可或角色
    • 使用Array时,包含设置的权限或者角色
  2. except属性

    • 用于明确定义拒绝权限或角色的访问
    • 使用String时,包含单一许可或角色
    • 使用Array时,包含设置的权限或者角色

重点
如果你同时使用了onlyexcept,那么你必须确保相互排除。

使用权限或者角色

在最简单的情况下,你允许有一个角色的权限来访问用户状态。你可以通过rolepermission通过onlyexcept属性,例如:

import { RouterModule, Routes } from '@angular/router';
import { NgModule } from '@angular/core';
import { HomeComponent } from './home/home.component';
import { NgxPermissionsGuard } from 'ngx-permissions';

const appRoutes: Routes = [
  { path: 'home',
    component: HomeComponent,
    canActivate: [NgxPermissionsGuard],
    data: {
      permissions: {
        only: 'ADMIN'  // 只有 ADMIN 的权限才能通过
      }
    }
  },
];
@NgModule({
  imports: [
    RouterModule.forRoot(appRoutes)
  ],
  exports: [
    RouterModule
  ]
})
export class AppRoutingModule {}

在这种情况下,NgxPermissionsGuard会检查当前权限是否允许通过。

多个权限或者角色

通常,几个权限/角色足以允许/拒绝用户访问的状态。然后将数组值派上用场。例如:

import { RouterModule, Routes } from '@angular/router';
import { NgModule } from '@angular/core';
import { HomeComponent } from './home/home.component';
import { NgxPermissionsGuard } from 'ngx-permissions';

const appRoutes: Routes = [
  { path: 'home',
    component: HomeComponent,
    canActivate: [NgxPermissionsGuard],
    data: {
      permissions: {
        // 只有 ADMIN 或者 MODERATOR 权限才能通过
        only: ['ADMIN', 'MODERATOR'],
        except: ['GUEST']
      }
    }
  },
];
@NgModule({
  imports: [
    RouterModule.forRoot(appRoutes)
  ],
  exports: [
    RouterModule
  ]
})
export class AppRoutingModule {}

在这种情况下,NgxPermissionsGuard会验证当前用户是否具有ADMIN或者MODERATOR权限,如果具备,那么将放行。

动态访问

你可以发现,需要动态地验证访问状态 - 通常取决于参数。

让我们想象一下用户想要去修改订单。我们需要每次都检查他当前的状态是否被允许。使用ActivatedRouteSnapshotRouterStateSnapshot对象来检查他是否能做到这一点。

为了兼容AOT模式,需要到处函数,下面是案例。

export function testPermissions(route: ActivatedRouteSnapshot, state: RouterStateSnapshot) {
  if (route.params['id'] === 42) {
    return ['MANAGER', "UTILS"]
  } else {
    return 'ADMIN'
  }
}
const appRoutes: Routes = [
  { path: 'dynamic/:id',
      component: HomeComponent,
      canActivate: [NgxPermissionsGuard],
      data: {
        permissions: {
          only: testPermissions
        }
      }
    }
];

注意,下面将不是AOT兼容的。

const appRoutes: Routes = [
  { path: 'dynamic/:id',
      component: HomeComponent,
      canActivate: [NgxPermissionsGuard],
      data: {
        permissions: {
          only: (route: ActivatedRouteSnapshot, state: RouterStateSnapshot) => {
              if (route.params['id'] === 42) {
                  return ['MANAGER', "UTILS"]
                } else {
                  return 'ADMIN'
                }
          }
        }
      }
    }
];

所以我们尝试访问id=42参数是否是正确的,如果正确将检查他的权限。ADMIN权限除外。

注意

此处的函数必须要返回角色或者权限的字符串,否则将不能工作。

redirectTo属性

  • 使用String 类型定义单个重定向规则
  • 使用Objects 类型定义单个/多个重定向规则
  • 使用Function 类型定义单个/多个动态重定向规则

单个重定向规则

路由的重定向路径没有被认证通过时你想要重定向到一些特殊的状态。

import { RouterModule, Routes } from '@angular/router';
import { NgModule } from '@angular/core';
import { HomeComponent } from './home/home.component';
import { NgxPermissionsGuard } from 'ngx-permissions';

const appRoutes: Routes = [
 { path: 'home',
   component: HomeComponent,
   canActivate: [NgxPermissionsGuard], // 路由守卫
   data: { // Angular Route的自由属性
     permissions: { // 权限属性
       only: ['ADMIN', 'MODERATOR'], // 只有 ADMIN或MODERATOR可以通过,否则将会重定向到/another-route
       redirectTo: '/another-route'
     }
   }
 },
];
@NgModule({
 imports: [
   RouterModule.forRoot(appRoutes)
 ],
 exports: [
   RouterModule
 ]
})
export class AppRoutingModule {}

为了像 params 使用通过redirectTo 作为对象传递附加属性,navigationCommandsnavigationExtras作为保留关键字,它被应用于传递路由参数。导航函数为 navigate(commands: any[], extras: NavigationExtras): Promise<boolean>

const appRoutes: Routes = [
 { path: 'home',
   component: HomeComponent,
   canActivate: [NgxPermissionsGuard], // 路由守卫
   data: {
     permissions: {
       // 只有ADMIN或MODERATOR权限才能通过
       only: ['ADMIN', 'MODERATOR'],
       redirectTo: {
           navigationCommands: ['123'],
           navigationExtras: {
               skipLocationChange: true
           }
       }               
   }
 },
];
@NgModule({
 imports: [
   RouterModule.forRoot(appRoutes)
 ],
 exports: [
   RouterModule
 ]
})

多个重定向规则

在某些情况下,你要基于拒绝权限或角色的前提下创建重定向策略来重定向用户。为了做到这一点,你必须创建一个包含KeysObject,表示拒绝权限或角色和值的重定向规则。

使用下面的值代表重定向规则。

值类型 返回值 使用
String String 简单的状态转换
Object Object 自定义参数或选项的重定向
Function String|Object 动态重定向

下面是基于角色或权限和状态的一多个重定向规则的例子。当用户没有权限访问状态时将会被重定向到agendaList,如果缺少canReadAgenda权限将会到达canEditAgendadashboarddefault属性被用来处理特定情况下重定向属性的默认重定向。

const appRoutes: Routes = [
{ path: 'home',
  component: HomeComponent,
  canActivate: [NgxPermissionsGuard],
  data: {
   permissions: {
           only: ['canReadAgenda','canEditAgenda'],
           redirectTo: {
             canReadAgenda: 'agendaList',
             canEditAgenda: 'dashboard',
             default: 'login'
           }
    }
  }
},
];
@NgModule({
imports: [
  RouterModule.forRoot(appRoutes)
],
exports: [
  RouterModule
]
})

上面案例的功能就是,如果当前用户没有权限的话就重定向到default,也就是login路由,如果是canReadAgenda就重定向到agendaList,如果是canEditAgenda就重定向到dashboard

如果你需要重定向参数Object更多的功能,你可以使用navigationCommands
navigationExtras

const appRoutes: Routes = [
{ path: 'home',
  component: HomeComponent,
  canActivate: [NgxPermissionsGuard],
  data: {
     permissions: {
           only: ['canEditAgenda'],
           redirectTo:{
             canEditAgenda: {
               navigationCommands: 'dashboard',
               navigationExtras: {
                   skipLocationChange: true
               }
             },
             default: 'login'
           }
     }
  }
},
];
@NgModule({
imports: [
  RouterModule.forRoot(appRoutes)
],
exports: [
  RouterModule
]
})  

上面的案例为当用户权限没canEditAgenda权限时将会重定向到login,如果有将会重定向到dashboard

下面是使用Function作为参数。

const appRoutes: Routes = [
{ path: 'home',
  component: HomeComponent,
  canActivate: [NgxPermissionsGuard],
  data: {
   permissions: {
          only: ['canReadAgenda','canEditAgenda'],
          redirectTo: {
            canReadAgenda: (rejectedPermissionName: string, activateRouteSnapshot: ActivatedRouteSnapshot, routeStateSnapshot: RouterStateSnapshot) => {
              return 'dashboard';
            },
            canEditAgenda: (rejectedPermissionName: string, activateRouteSnapshot: ActivatedRouteSnapshot, routeStateSnapshot: RouterStateSnapshot) => {
              return {
                  navigationCommands: ['/dashboard'],
                  navigationExtras: {
                      skipLocationChange: true
                  }
              }
            },
            default: 'login'
        }
    }
  }
},
];
@NgModule({
imports: [
  RouterModule.forRoot(appRoutes)
],
exports: [
  RouterModule
]
})

如果要兼容AOT模式,需要将函数提取出来。前面已经提到过。例如:

export function canReadAgenda(rejectedPermissionName: string, activateRouteSnapshot: ActivatedRouteSnapshot, routeStateSnapshot: RouterStateSnapshot) => {                                                 
    return 'dashboard';
},

redirectTo: {
    canReadAgenda: canReadAgenda
 
}

动态重定向规则

下面的例子是基于ActivatedRouteSnapshotRouterStateSnapshot参数实现动态访问状态并重定向功能。

const appRoutes: Routes = [
{ path: 'home/:isEditable',
  component: HomeComponent,
  canActivate: [NgxPermissionsGuard],
  data: {
  permissions: {
         only: ['canReadAgenda','canEditAgenda'],
         redirectTo: (rejectedPermissionName: string, activateRouteSnapshot: ActivatedRouteSnapshot, routerStateSnapshot: RouterStateSnapshot) => {
           if(activateRouteSnapshot.params['id'] === 42){
             return 'login';
           } else {
             return 'dashboard'
           }
         }
  }
},
];
@NgModule({
imports: [
  RouterModule.forRoot(appRoutes)
],
exports: [
  RouterModule
]
})

同样为了兼容AOT模式需要这样写:

export function redirectToFunc(rejectedPermissionName: string, activateRouteSnapshot: ActivatedRouteSnapshot, routerStateSnapshot: RouterStateSnapshot) => {
     if(activateRouteSnapshot.params['id'] === 42){
       return 'login';
     } else {
       return 'dashboard'
     }
   }

redirectTo: redirectToFunc

实现守卫

Can Activate 守卫

可以使用NgxPermissionsGuard实现的CanActivate接口,上面大部分案例已经使用过了。

Can Load 守卫

使用NgxPermissionsGuard实现的CanLoad接口,功能和canActivate类似。

const appRoutes: Routes = [
  {
    path: 'lazy',
    data: {
      permissions: {
        except: 'ADDDMIN',
      }
    },
    canLoad: [NgxPermissionsGuard],
    loadChildren: 'app/lazy-module/lazy-module.module#LazyModule'
  },
 

];
@NgModule({
  imports: [
    RouterModule.forRoot(appRoutes)
  ],
  exports: [
    RouterModule
  ],
  providers: [
    // CanDeactivateGuard
  ]
})
export class AppRoutingModule {}

only属性也可以自定义实现,参数是Route

{
    path: 'lazy',
    data: {
      permissions: {
         only: (route: Route) => {
                  //logic here
                   return ['MANAGER', "UTILS"]
                  }
      }
    },
    canLoad: [NgxPermissionsGuard],
    loadChildren: 'app/lazy-module/lazy-module.module#LazyModule'
},

Can Activate Child 守卫

使用NgxPermissionsGuard实现的CanLoad接口,功能和canActivate类似。

const appRoutes: Routes = [
  { path: '',
    component: IsolateComponent,
    canActivateChild: [NgxPermissionsGuard],
    children: [
      {
        path: 'except-should',
        component: AnotherComponent,
        data: {
          permissions: {
            except: 'ADMIN'
          }
        }
      },
      {
        path: 'only-should',
        component: ComeComponent,
        data: {
          permissions: {
            only: 'GUEST'
          }
        }
      },
    ]
  },
];
发布了145 篇原创文章 · 获赞 357 · 访问量 44万+

猜你喜欢

转载自blog.csdn.net/wf19930209/article/details/104244748
今日推荐