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

Angular中如何基于用户角色限制组件访问?

Angular 角色权限控制实现方案

1. 改造 UserService:管理用户角色状态

首先完善用户服务的角色存储与获取逻辑,确保登录后能持久化并读取用户角色信息:

// user.service.ts
import { Injectable } from '@angular/core';
import { BehaviorSubject, Observable } from 'rxjs';

// 定义用户结构,包含角色数组
export interface User {
  id: number;
  username: string;
  roles: string[]; // 示例:['admin', 'user']
}

@Injectable({ providedIn: 'root' })
export class UserService {
  private currentUserSubject: BehaviorSubject<User | null>;
  public currentUser$: Observable<User | null>;

  constructor() {
    // 从 localStorage 初始化用户信息(登录后存储)
    const storedUser = localStorage.getItem('currentUser');
    this.currentUserSubject = new BehaviorSubject<User | null>(storedUser ? JSON.parse(storedUser) : null);
    this.currentUser$ = this.currentUserSubject.asObservable();
  }

  // 获取当前用户的同步值(守卫中直接调用)
  public get currentUser(): User | null {
    return this.currentUserSubject.value;
  }

  // 登录方法:替换为实际后端请求,获取带角色的用户信息
  login(username: string, password: string): boolean {
    // 这里用模拟数据示例,实际要调用后端接口
    const mockUser: User = {
      id: 1,
      username,
      roles: username === 'admin' ? ['admin'] : username === 'user' ? ['user'] : ['client']
    };

    // 存储用户信息到 localStorage 和状态流
    localStorage.setItem('currentUser', JSON.stringify(mockUser));
    this.currentUserSubject.next(mockUser);
    return true;
  }

  // 登出清理用户信息
  logout(): void {
    localStorage.removeItem('currentUser');
    this.currentUserSubject.next(null);
  }
}

2. 升级 AuthGuard:添加角色校验逻辑

将原登录守卫扩展为支持角色校验的守卫,通过路由data参数获取所需角色,与当前用户角色对比:

// auth.guard.ts
import { Injectable } from '@angular/core';
import { CanActivate, ActivatedRouteSnapshot, RouterStateSnapshot, Router } from '@angular/router';
import { UserService } from './user.service';

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

  canActivate(route: ActivatedRouteSnapshot, state: RouterStateSnapshot): boolean {
    const currentUser = this.userService.currentUser;
    
    // 先校验是否登录
    if (!currentUser) {
      // 未登录跳转登录页,记录当前路由以便登录后返回
      this.router.navigate(['/login'], { queryParams: { returnUrl: state.url } });
      return false;
    }

    // 获取路由配置中要求的角色列表
    const requiredRoles = route.data['requiredRoles'] as string[];
    if (!requiredRoles) {
      // 无角色要求的路由直接放行
      return true;
    }

    // 校验用户是否拥有任一所需角色
    const hasPermission = currentUser.roles.some(role => requiredRoles.includes(role));
    if (hasPermission) {
      return true;
    } else {
      // 无权限跳转至无权限提示页
      this.router.navigate(['/unauthorized']);
      return false;
    }
  }
}

3. 配置路由:给仪表盘分配角色权限

在路由模块中,为每个仪表盘路由绑定守卫,并通过data.requiredRoles指定允许访问的角色:

// app-routing.module.ts
import { NgModule } from '@angular/core';
import { RouterModule, Routes } from '@angular/router';
import { AuthGuard } from './auth.guard';
import { AdminDashboardComponent } from './admin-dashboard/admin-dashboard.component';
import { UserDashboardComponent } from './user-dashboard/user-dashboard.component';
import { ClientDashboardComponent } from './client-dashboard/client-dashboard.component';
import { LoginComponent } from './login/login.component';
import { UnauthorizedComponent } from './unauthorized/unauthorized.component';

const routes: Routes = [
  { path: 'login', component: LoginComponent },
  { path: 'unauthorized', component: UnauthorizedComponent },
  // 管理员仪表盘:仅 admin 角色可访问
  {
    path: 'admin-dashboard',
    component: AdminDashboardComponent,
    canActivate: [AuthGuard],
    data: { requiredRoles: ['admin'] }
  },
  // 普通用户仪表盘:仅 user 角色可访问
  {
    path: 'user-dashboard',
    component: UserDashboardComponent,
    canActivate: [AuthGuard],
    data: { requiredRoles: ['user'] }
  },
  // 客户仪表盘:仅 client 角色可访问
  {
    path: 'client-dashboard',
    component: ClientDashboardComponent,
    canActivate: [AuthGuard],
    data: { requiredRoles: ['client'] }
  },
  { path: '', redirectTo: '/login', pathMatch: 'full' },
  { path: '**', redirectTo: '/login' }
];

@NgModule({
  imports: [RouterModule.forRoot(routes)],
  exports: [RouterModule]
})
export class AppRoutingModule { }

额外优化建议

  • 把角色定义为常量避免硬编码:比如export const Roles = { ADMIN: 'admin', USER: 'user', CLIENT: 'client' },在路由和服务中统一使用。
  • 若需要支持多角色访问(如 admin 可访问用户仪表盘),可调整守卫的校验逻辑,放宽角色匹配条件。
  • 在登录组件中调用UserService.login(),登录成功后根据用户角色跳转对应仪表盘,或返回之前的目标路由。

内容的提问来源于stack exchange,提问作者afsar siddique

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.30 00:13:28