首页 > 解决方案 > 如何在 Angular 中使用 AuthGuard 为两个不同的用户角色提供相同菜单的路由访问权限?

问题描述

我有一个具有三个用户角色的应用程序:ROLE_USER、ROLE_MODERATOR 和 ROLE_ADMIN,如下所示:

export enum Role {
    User = 'ROLE_USER',
    Moderator = 'ROLE_MODERATOR',
    Admin = 'ROLE_ADMIN'
}

我有一个名为“配置文件”的菜单,ROLE_MODERATOR 和 ROLE_ADMIN 可以访问它。成功登录版主和管理员后可以看到此菜单。我正在使用 AuthGuard 限制未经授权的用户访问配置文件菜单,在这种情况下,只有版主和管理员可以访问它。我在我的 app.module.ts 文件中放置了配置文件菜单的 AuthGuard,如下所示:

path: 'profile', component: ProfileComponent, canActivate: [AuthGuardService], data: { roles: [Role.Admin, Role.Moderator] }, pathMatch: 'full' }

我的用户类如下:

export class User {
    username: string;
    password: string;
    role: Role;
}

我的 AuthGuard 类如下:

export class AuthGuardService implements CanActivate {
  isLoggedIn: boolean;

  constructor(private router: Router,
    private tokenService: TokenStorageService,
    private auth: AuthService) { }

  canActivate(route: ActivatedRouteSnapshot, state: RouterStateSnapshot) {
    const currentUser = this.tokenService.getUser();
    this.isUserLoggedIn = this.tokenService.getToken();

    if (this.isLoggedIn) {
      if (currentUser.roles == 'ROLE_ADMIN' || currentUser.roles == 'ROLE_MODERATOR') {
        return true;
      }
      this.router.navigate(['/']);
      return false;
    }
  }

  isUserLoggedInn() {
    if (this.tokenService.getToken()) {
      this.isLoggedIn = true;
    }
  }
}

在上面的代码中有一个简单的逻辑,它会检查用户是否登录。如果用户登录,它将检查当前用户角色。如果用户的角色是管理员或版主,它应该能够从他们各自的帐户访问配置文件菜单,我希望我已经在 app.module.ts 类中正确配置了配置文件菜单。但它没有按预期工作,所以我在这里做错了。任何帮助或建议都会很棒。提前致谢。

标签: angular

解决方案


我看到您正在使用“数据”通过路由传递“允许的角色”。但是,您并没有在警卫中使用它。

data: { roles: [Role.Admin, Role.Moderator] }

您可以通过执行以下操作使任何角色(以及未来角色)的警卫动态化:

export class AuthGuardService implements CanActivate {
    isLoggedIn: boolean;
  
    constructor(private router: Router,
      private tokenService: TokenStorageService,
      private auth: AuthService) { }
  
    canActivate(route: ActivatedRouteSnapshot, state: RouterStateSnapshot) {
      // Gets the roles from route data
      const roles = route.data['roles'] as Array<string>;

      const currentUser = this.tokenService.getUser();
      this.isUserLoggedIn = this.tokenService.getToken();
  
      if (this.isUserLoggedIn) {
        
        // Considering currentUser.roles is a single value and not an array 
        for (let i = 0; i < roles.length; i++) {
            if (currentUser.roles == roles[i]) {
                return true
            }
        }

        // Considering currentUser.roles is an array of roles allotted to the user, then uncomment the below code
        // for (let i = 0; i < roles.length; i++) {
        //     if (currentUser.roles.findIndex(x => x.roleName == roles[i]) != -1) {
        //         return true;
        //     }
        // }

        this.router.navigate(['/']);
        return false;
      }
    }

  }

推荐阅读