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

如何在Angular中实现通用的基于角色的路由权限控制?

Angular 基于角色的路由权限控制实现方案

一、扩展路由配置,添加角色元数据

在路由规则中通过data字段指定该路由所需的角色,让守卫可以动态获取权限要求:

const routes: Routes = [
  { path: '', component: AuthComponent},
  // 修正拼写错误:assitants → assistants
  { 
    path: 'assistants', 
    component: AssistantsComponent, 
    canActivate: [AuthGuard],
    data: { roles: ['admin'] } // 仅允许admin角色访问
  },
  { 
    path: 'client', 
    component: ClientComponent,
    canActivate: [AuthGuard],
    data: { roles: ['client'] } // 仅允许client角色访问
  }
];

二、改造AuthGuard,实现角色校验逻辑

在现有登录校验基础上,加入角色匹配逻辑。从token中解析用户角色后,与路由要求的角色对比:

import { Injectable } from '@angular/core';
import { CanActivate, ActivatedRouteSnapshot, RouterStateSnapshot, Router, UrlTree } from '@angular/router';

@Injectable({
  providedIn: 'root'
})
export class AuthGuard implements CanActivate {
  static readonly LOCAL_STORAGE_ACCESS_TOKEN = 'access_token';

  // 注入Router用于页面跳转
  constructor(private router: Router) {}

  canActivate(
    route: ActivatedRouteSnapshot,
    state: RouterStateSnapshot
  ): boolean | UrlTree {
    const accessToken = localStorage.getItem(AuthGuard.LOCAL_STORAGE_ACCESS_TOKEN);
    
    // 未登录则跳转至登录页
    if (!accessToken) {
      return this.router.createUrlTree(['/']);
    }

    // 从JWT token中解析用户角色(根据你的token格式调整解析逻辑)
    const userRoles = this.parseRolesFromToken(accessToken);
    // 获取路由配置的必填角色
    const requiredRoles = route.data['roles'] as string[];

    // 校验角色权限
    if (requiredRoles?.length) {
      const hasPermission = requiredRoles.some(role => userRoles.includes(role));
      if (!hasPermission) {
        // 无权限时跳转至登录页或自定义403页面
        return this.router.createUrlTree(['/']);
      }
    }

    return true;
  }

  private parseRolesFromToken(token: string): string[] {
    try {
      // JWT的payload是base64编码的第二部分
      const payload = JSON.parse(atob(token.split('.')[1]));
      return payload.roles || [];
    } catch (err) {
      console.error('Token解析失败:', err);
      return [];
    }
  }
}

三、通用化权限拆分(可选)

将登录校验和角色校验拆分为两个独立守卫,职责更单一,便于复用和扩展:

1. 单独实现RoleGuard

import { Injectable } from '@angular/core';
import { CanActivate, ActivatedRouteSnapshot, Router, UrlTree } from '@angular/router';

@Injectable({ providedIn: 'root' })
export class RoleGuard implements CanActivate {
  constructor(private router: Router) {}

  canActivate(route: ActivatedRouteSnapshot): boolean | UrlTree {
    const accessToken = localStorage.getItem(AuthGuard.LOCAL_STORAGE_ACCESS_TOKEN);
    const userRoles = this.parseRolesFromToken(accessToken!);
    const requiredRoles = route.data['roles'] as string[];

    if (!requiredRoles.some(role => userRoles.includes(role))) {
      return this.router.createUrlTree(['/forbidden']);
    }
    return true;
  }

  private parseRolesFromToken(token: string): string[] {
    try {
      const payload = JSON.parse(atob(token.split('.')[1]));
      return payload.roles || [];
    } catch (err) {
      console.error('Token解析失败:', err);
      return [];
    }
  }
}

2. 路由中组合使用守卫

const routes: Routes = [
  { path: '', component: AuthComponent},
  { 
    path: 'assistants', 
    component: AssistantsComponent, 
    canActivate: [AuthGuard, RoleGuard], // 先校验登录状态,再校验角色权限
    data: { roles: ['admin'] }
  },
  { 
    path: 'client', 
    component: ClientComponent,
    canActivate: [AuthGuard, RoleGuard],
    data: { roles: ['client'] }
  }
];

这种拆分方式让每个守卫专注单一职责,后续新增权限规则时,只需调整RoleGuard或新增守卫即可。


内容的提问来源于stack exchange,提问作者Marek Vondra

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.08 22:30:27