You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何用CanMatchFn和CanActivateFn实现Angular认证守卫(类转函数)

问题描述

我有如下Angular AuthGuard:

@Injectable({
    providedIn: 'root',
})
export class AuthGuard implements CanActivate, CanLoad {
    constructor(private authService: AuthService, private router: Router) {}

    canActivate(
        next: ActivatedRouteSnapshot,
        state: RouterStateSnapshot,
    ): | Observable<boolean | UrlTree> | Promise<boolean | UrlTree> | boolean | UrlTree {
        return this.isAuthenticated();
    }

    canLoad(
        route: Route,
        segments: UrlSegment[],
    ): | boolean | UrlTree | Observable<boolean | UrlTree> | Promise<boolean | UrlTree> {
        return this.isAuthenticated();
    }

    isAuthenticated(): | boolean | UrlTree | Observable<boolean | UrlTree> | Promise<boolean | UrlTree> {
        return this.authService.isAuthenticated$.pipe(
            take(1),
            tap((isAuthenticated: boolean) => {
                if (!isAuthenticated) {
                    this.router.navigate(['/account/login']);
                }
            }),
        );
    }
}

我已升级至Angular 15:

Angular CLI: 15.2.0
Node: 16.19.1
Package Manager: npm 8.19.3
OS: darwin x64

Angular: 15.2.0

Package                         Version
---------------------------------------------------------
@angular-devkit/core            15.2.0
@angular-devkit/schematics      15.2.0
@schematics/angular             15.2.0

现在收到TS弃用提示:CanActivate已弃用,建议使用CanActivateFn;CanLoad已弃用,建议使用CanMatchFn。我尝试查找如何用CanActivateFn和CanMatchFn实现AuthGuard,但找不到能实现未认证时跳转至/account/login路由功能的合适资源,请问如何正确实现这类简易Angular认证守卫?


解决方案

Angular 15+推荐使用函数式守卫替代类守卫,核心是用inject()函数获取依赖,直接返回认证判断结果(包含路由跳转逻辑)。

1. 提取通用认证逻辑

先封装通用的认证校验函数,返回Observable<boolean | UrlTree>类型:

import { inject } from '@angular/core';
import { Router, UrlTree } from '@angular/router';
import { Observable, take, map } from 'rxjs';
import { AuthService } from './auth.service';

const checkAuthentication = (): Observable<boolean | UrlTree> => {
  const authService = inject(AuthService);
  const router = inject(Router);

  return authService.isAuthenticated$.pipe(
    take(1),
    map((isAuthenticated: boolean) => {
      // 未认证时返回UrlTree,Angular会自动处理跳转
      return isAuthenticated || router.createUrlTree(['/account/login']);
    })
  );
};

注意:不再使用tap调用router.navigate,直接返回UrlTree是函数式守卫的标准写法,更符合守卫的设计逻辑。

2. 定义守卫函数

基于通用逻辑创建CanActivateFn和CanMatchFn:

import { CanActivateFn, CanMatchFn } from '@angular/router';

export const authActivateGuard: CanActivateFn = () => {
  return checkAuthentication();
};

export const authMatchGuard: CanMatchFn = () => {
  return checkAuthentication();
};

3. 路由配置中使用

修改路由配置,替换原类守卫为新的函数式守卫:

import { Routes } from '@angular/router';
import { authActivateGuard, authMatchGuard } from './auth.guard';

const routes: Routes = [
  {
    path: 'dashboard',
    component: DashboardComponent,
    // 替代原canActivate: [AuthGuard]
    canActivate: [authActivateGuard],
    // 替代原canLoad: [AuthGuard]
    canMatch: [authMatchGuard]
  },
  // 其他路由配置...
];

核心要点

  • 函数式守卫无需@Injectable装饰器,通过inject()直接获取依赖,Angular自动处理注入。
  • CanMatchFn完全替代CanLoad的功能,用于懒加载路由的权限校验。
  • 返回UrlTree是Angular官方推荐的跳转方式,确保守卫逻辑的一致性和可预测性。

内容的提问来源于stack exchange,提问作者Lorraine Ram-El

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.30 08:10:46