面试题答案
一键面试利用Angular路由守卫实现多角色权限管理
- CanActivate守卫实现访问权限控制
- 创建守卫类:
- 首先创建一个实现
CanActivate
接口的守卫类,例如AuthGuard
。 - 在类中注入必要的服务,如用于获取用户角色和权限信息的
AuthService
。
import { Injectable } from '@angular/core'; import { CanActivate, ActivatedRouteSnapshot, RouterStateSnapshot, Router } from '@angular/router'; import { AuthService } from './auth.service'; @Injectable({ providedIn: 'root' }) export class AuthGuard implements CanActivate { constructor(private authService: AuthService, private router: Router) {} canActivate( next: ActivatedRouteSnapshot, state: RouterStateSnapshot ): boolean | Promise<boolean> | Observable<boolean> { const userRole = this.authService.getUserRole(); const routePermissions = next.data['permissions']; if (routePermissions.includes(userRole)) { return true; } else { this.router.navigate(['/forbidden']); return false; } } }
- 首先创建一个实现
- 配置路由:
- 在
app - routing.module.ts
中,为需要权限控制的路由配置canActivate
属性。
const routes: Routes = [ { path: 'admin - dashboard', component: AdminDashboardComponent, canActivate: [AuthGuard], data: { permissions: ['admin'] } }, { path: 'user - dashboard', component: UserDashboardComponent, canActivate: [AuthGuard], data: { permissions: ['user', 'admin'] } } ];
- 在
- 创建守卫类:
- CanDeactivate守卫实现离开页面权限控制(可选,根据业务需求)
- 创建守卫类:
- 创建实现
CanDeactivate
接口的守卫类,例如LeaveGuard
。同样注入必要服务。
import { Injectable } from '@angular/core'; import { CanDeactivate, ActivatedRouteSnapshot, RouterStateSnapshot } from '@angular/router'; import { SomeComponent } from './some.component'; @Injectable({ providedIn: 'root' }) export class LeaveGuard implements CanDeactivate<SomeComponent> { canDeactivate( component: SomeComponent, currentRoute: ActivatedRouteSnapshot, currentState: RouterStateSnapshot, nextState?: RouterStateSnapshot ): boolean | Observable<boolean> | Promise<boolean> { // 检查用户角色和当前页面离开权限规则 const userRole = this.authService.getUserRole(); if (component.canLeave(userRole)) { return true; } else { return confirm('You do not have permission to leave this page.'); } } }
- 创建实现
- 配置路由:
- 在
app - routing.module.ts
中,为需要离开权限控制的路由配置canDeactivate
属性。
const routes: Routes = [ { path:'sensitive - page', component: SensitivePageComponent, canDeactivate: [LeaveGuard] } ];
- 在
- 创建守卫类:
大量路由和复杂权限规则下的优化
- 缓存权限数据
- 在
AuthService
中,缓存用户的权限信息。例如,在用户登录成功后,将用户角色和对应的权限列表缓存起来。 - 每次
CanActivate
守卫检查权限时,优先从缓存中获取权限数据,而不是重复从后端获取,减少网络请求次数。
- 在
- 减少守卫逻辑复杂度
- 将复杂的权限判断逻辑提取到独立的服务方法中,使得
CanActivate
守卫的canActivate
方法保持简洁。例如,将权限匹配逻辑封装到AuthService
的hasPermission
方法中。 - 这样,当权限规则发生变化时,只需要修改
hasPermission
方法,而不需要修改多个守卫的逻辑。
- 将复杂的权限判断逻辑提取到独立的服务方法中,使得
- 延迟加载路由和守卫
- 对于不常用的路由模块,使用Angular的延迟加载功能。这样,只有在用户实际访问相关路由时,才会加载对应的模块及其守卫。
- 在路由配置中,通过
loadChildren
属性实现延迟加载。
const routes: Routes = [ { path: 'rare - page', loadChildren: () => import('./rare - page.module').then(m => m.RarePageModule), canActivate: [AuthGuard] } ];
- 使用共享守卫实例
- 在应用中,尽量使用同一个守卫实例来处理权限检查,避免每次路由变化都创建新的守卫实例。Angular的依赖注入系统默认会为每个注入点提供单例实例,确保守卫实例的一致性。
- 基于角色的权限分组
- 对大量路由进行基于角色的权限分组。例如,将所有管理员权限的路由放在一个模块中,所有普通用户权限的路由放在另一个模块中。这样,在权限检查时,可以快速定位到对应的权限范围,减少检查的复杂度。