Angular之ngx-permissions的路由使用
介绍
现在,你准备开始与控制访问应用程序的状态工作。为了限制任何状态ngx-permission
需要依靠 Angular Route 数据属性,通过permissions
间接控制认证配置。
Permissions
对象接受以下属性:
属性 | 接受值 |
---|---|
only | String|Array|Function |
except | String|Array|Function |
redirectTo | String |
only和except属性
-
only属性
- 用于明确定义权限或角色被允许访问的状态
- 使用
String
时,包含单一许可或角色 - 使用
Array
时,包含设置的权限或者角色
-
except属性
- 用于明确定义拒绝权限或角色的访问
- 使用
String
时,包含单一许可或角色 - 使用
Array
时,包含设置的权限或者角色
重点:
如果你同时使用了only
和except
,那么你必须确保相互排除。
使用权限或者角色
在最简单的情况下,你允许有一个角色的权限来访问用户状态。你可以通过role
或permission
通过only
或except
属性,例如:
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
权限,如果具备,那么将放行。
动态访问
你可以发现,需要动态地验证访问状态 - 通常取决于参数。
让我们想象一下用户想要去修改订单。我们需要每次都检查他当前的状态是否被允许。使用ActivatedRouteSnapshot
和RouterStateSnapshot
对象来检查他是否能做到这一点。
为了兼容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
作为对象传递附加属性,navigationCommands
和navigationExtras
作为保留关键字,它被应用于传递路由参数。导航函数为 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
]
})
多个重定向规则
在某些情况下,你要基于拒绝权限或角色的前提下创建重定向策略来重定向用户。为了做到这一点,你必须创建一个包含Keys
的Object
,表示拒绝权限或角色和值的重定向规则。
使用下面的值代表重定向规则。
值类型 | 返回值 | 使用 |
---|---|---|
String |
String |
简单的状态转换 |
Object |
Object |
自定义参数或选项的重定向 |
Function |
String|Object |
动态重定向 |
下面是基于角色或权限和状态的一多个重定向规则的例子。当用户没有权限访问状态时将会被重定向到agendaList
,如果缺少canReadAgenda
权限将会到达canEditAgenda
的dashboard
。default
属性被用来处理特定情况下重定向属性的默认重定向。
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
}
动态重定向规则
下面的例子是基于ActivatedRouteSnapshot
和RouterStateSnapshot
参数实现动态访问状态并重定向功能。
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'
}
}
},
]
},
];