之后我们就可以在 app-routing.module.ts 文件中引入 AuthGuard 类,针对需要保护的路由进行路由守卫的配置
import { NgModule } from '@angular/core'; import { Routes, RouterModule } from '@angular/router'; // 引入组件 import { CrisisListComponent } from './crisis-list/crisis-list.component'; // 引入路由守卫 import { AuthGuard } from './auth/auth.guard'; const routes: Routes = [ { path: 'crisis-center', component: CrisisListComponent, canActivate: [AuthGuard], // 添加针对当前路由的 canActivate 路由守卫 } ]; @NgModule({ imports: [RouterModule.forRoot(routes)], exports: [RouterModule], }) export class AppRoutingModule { } 4.2.2、CanActivateChild:针对子路由的认证授权与继承 CanActivate 接口进行路由守卫的方式相似,针对子路由的认证授权可以通过继承 CanActivateChild 接口来实现,因为授权的逻辑很相似,这里通过多重继承的方式,扩展 AuthGuard 的功能,从而达到同时针对路由和子路由的路由守卫
改造下原先 canActivate 方法的实现,将认证逻辑修改为用户的 token 信息中包含 admin 即可访问 crisis-center 页面,在针对子路由进行认证授权的 canActivateChild 方法中,通过判断 token 信息是否为 admin-master 模拟完成对于子路由的访问认证
import { Injectable } from '@angular/core'; import { CanActivate, ActivatedRouteSnapshot, RouterStateSnapshot, UrlTree, Router, CanActivateChild } from '@angular/router'; import { Observable } from 'rxjs'; @Injectable({ providedIn: 'root' }) export class AuthGuard implements CanActivate, CanActivateChild { /** * ctor * @param router 路由 */ constructor(private router: Router) { } canActivate( next: ActivatedRouteSnapshot, state: RouterStateSnapshot): Observable<boolean | UrlTree> | Promise<boolean | UrlTree> | boolean | UrlTree { // 判断是否有 token 信息 let token = localStorage.getItem('auth-token') || ''; if (token === '') { this.router.navigate(['/login']); return false; } // 判断是否可以访问当前连接 let url: string = state.url; if (token.indexOf('admin') !== -1 && url.indexOf('/crisis-center') !== -1) { return true; } this.router.navigate(['/login']); return false; } canActivateChild( childRoute: ActivatedRouteSnapshot, state: RouterStateSnapshot): boolean | UrlTree | Observable<boolean | UrlTree> | Promise<boolean | UrlTree> { let token = localStorage.getItem('auth-token') || ''; if (token === '') { this.router.navigate(['/login']); return false; } return token === 'admin-master'; } }通过 Angular CLI 新增一个 crisis-detail 组件,作为 crisis-list 的子组件
ng g component crisis-detail接下来在 crisis-list 中添加 router-outlet 标签,用来定义子路由的渲染出口
<h2>危机中心</h2> <ul> <li *ngFor="let crisis of crisisList"> <a [routerLink]="[crisis.id]"> <span>{{ crisis.id }}</span>{{ crisis.name }} </a> </li> </ul> <!-- 定义子路由的渲染出口 --> <router-outlet></router-outlet>在针对子路由的认证授权配置时,我们可以选择针对每个子路由添加 canActivateChild 属性,也可以定义一个空地址的子路由,将所有归属于 crisis-list 的子路由作为这个空路由的子路由,通过针对这个空路径添加 canActivateChild 属性,从而实现将守护规则应用到所有的子路由上
这里其实相当于将原先两级的路由模式(父:crisis-list,子:crisis-detail)改成了三级(父:crisis-list,子:' '(空路径),孙:crisis-detail)
import { NgModule } from '@angular/core'; import { Routes, RouterModule } from '@angular/router'; // 引入组件 import { CrisisListComponent } from './crisis-list/crisis-list.component'; import { CrisisDetailComponent } from './crisis-detail/crisis-detail.component'; // 引入路由守卫 import { AuthGuard } from './auth/auth.guard'; const routes: Routes = [ { path: 'crisis-center', component: CrisisListComponent, canActivate: [AuthGuard], // 添加针对当前路由的 canActivate 路由守卫 children: [{ path: '', canActivateChild: [AuthGuard], // 添加针对子路由的 canActivate 路由守卫 children: [{ path: 'detail', component: CrisisDetailComponent }] }] } ]; @NgModule({ imports: [RouterModule.forRoot(routes)], exports: [RouterModule], }) export class AppRoutingModule { }