如何使用Angular 2管理用户角色和权限

27
我正在开发一个新的Angular2应用程序,并想知道如何管理某些角色和权限可以访问的路由,以及如何创建、编辑和删除某些角色的项目。
我想知道如何解决以下问题:
- 如何管理对一些UI元素的访问权限?应用程序如何知道是否显示或隐藏它?您使用单个服务来处理吗?还是为应用程序中不同位置创建不同的条件? - 如何管理应用程序的路由?您使用CanActivate、CanActivateChild、CanLoad等方法吗?您会为所有路由构建单个保护程序吗?还是为不同模块或组件创建不同的保护程序? - 最后一个问题。将应用程序分成哪些部分以便像CMS一样销售最佳?我的意思是,我们如何实现从市场加载其他模块并将其添加到应用程序中的可能性?
您如何解决类似的问题?
如果您有任何指导、经验或材料可以涵盖这些主题,我将非常感激。提前致谢。

4
这个问题在SO的问答格式中过于宽泛。整本书的章节都可以用来讲解如何解决这些问题。简单来说,需要关注路由、认证保护和模块。 - AJ X.
@axlj 是的,我明白了。你说得对。但是你怎么知道现在有很多人不喜欢读书呢?而且更多有好想法的人可能永远不会写一本书。但是如果所有这些人都写一些简短的回答,那么我们就可以有一个地方,让那些不喜欢读书的人也能了解这个问题,并添加他们自己的想法 :) - Roman Skydan
我明白你的想法,我也更喜欢创作而不是读长篇大论的书。不幸的是,对于这个具体问题的完整回答可能需要读很多书! - AJ X.
3个回答

25

正如在您的问题的评论中提到的,完整的答案超出了SO问题/回答的范围,因此您可能会发现您的问题因此被关闭,但是这里有一些快速建议供您自行探索:

  • 通过http / https在登录期间/之后从服务器获取用户的权限。在适合您的应用程序的地方存储这些权限,例如在服务中。如果使用JWT,则可以在JWT令牌中返回权限。

  • 为简化事情,只在客户端处理权限。角色用于服务器代码确定用户具有哪些权限。在客户端上没有必要将角色与权限混淆。

  • 使用身份验证守卫保护路由

  • 使用*ngIf或ngSwitch/*ngSwitchCase保护单个UI元素

  • 动态加载是一个大的主题领域-去阅读相关资料-网络上有很多资源。然而,据我所知,虽然您可以懒惰地加载模块,但它们必须在编译时为应用程序所知道。我可能错了,但我认为您不能随意在运行时加载任何内容。


一些应用程序在编译时具有未知组件;因此,在这种情况下应使用动态组件。 - FindOutIslamNow

12

我曾在一款应用上实现过类似的功能,以下是我的处理方式。

我创建了一个认证服务,其中包含了一个方法,用于检查用户是否有管理角色:

auth.service.ts

public isManager(): boolean {
    let isManager = false;
    let user = this.getUserToken();
    //Stored my allowed groups in a config file, comma separated string
    let allowedGroups = AuthenticationParams.filters.split(',');
    let userGroups: any;
    if (user !== null && user !== undefined) {
      try {
        let userGroups: any = user.role;
        if (userGroups !== undefined && userGroups !== null && userGroups.length > 0) {
          try {
            userGroups.forEach((e: any) => {
              if (allowedGroups.indexOf(e) > -1) {
                isManager = true;
              }
            });
          } catch (e) {
            if (allowedGroups.indexOf(userGroups) > -1) {
              isManager = true;
            }
          }
        }
      } catch (e) {
        isManager = false;
      }
    }
    return isManager;
}

public getUserToken(): any {
    return localStorage.getItem('jwtTokenName');
}

我创建了一个身份验证守卫,代码如下:

guard.component.ts

import { Injectable, OnInit } from '@angular/core';
import { CanActivate, CanActivateChild } from '@angular/router';
import { Router } from '@angular/router'; 
import { AuthenticationService } from '../services/helper/security/auth.service';

@Injectable()
export class GuardComponent implements CanActivate {

  constructor(private authenticationService: AuthenticationService, private _router: Router) {
  }

  canActivate() {
    let isManager: boolean = this.authenticationService.isManager();
    if (!isManager) {
      this._router.navigate(['unauthorized']);
    }
    return isManager;
  }
}

guard.module.ts

import { NgModule } from '@angular/core';
import { CommonModule } from '@angular/common';
import { GuardComponent } from './guard.component';

@NgModule({
  declarations: [],
  imports: [ CommonModule ],
  exports: [],
  providers: [ GuardComponent ],
})
export class GuardModule { }

我使用了用于管理到管理员区域导航的路由守卫。

app-routing.module.ts

{ path: 'management', component: AdminComponent, canActivate: [GuardComponent] }

在我的导航栏中,我只调用isManager方法并将其存储在一个变量中,然后使用该变量来确定是否需要显示管理链接。

navbar.component.ts

public isManager: boolean = false;

ngOnInit(): void {
    this.isManager = this.authenticationService.isManager();
}

导航栏组件.html

<li [routerLinkActive]="['active']" *ngIf="isManager"><a [routerLink]="['management']">Management Portal</a></li>

我不得不从每个方法中删除一些数据,但这会给你一个基本的想法。希望这可以帮助到你。


1
那么如果我们有许多角色,大约30个,我们需要为它们所有创建isRole()吗? - DevEng
这将取决于哪些角色需要访问哪些页面。例如,如果有10个角色可以访问1个页面,则在访问该页面之前只需检查这些角色即可。 - Wesley Coetzee

8
这个问题相当广泛,我不认为你可以在这个答案中轻松地涵盖它。基本上有三件事与之相关。
- 路由 - 守卫 - 模块
你需要一个单一的守卫模块来检查整个应用程序,所有子路由将成为守卫路由的子级。简而言之,它将像全局守卫一样为您的整个应用程序提供保护。你的路由将被简化。更多关于守卫的信息请参考这里
现在说到模块,你需要将所有内容分成常见和特色模块,并重复使用这些模块或独立使用它们。这将帮助你将其销售为CMS。更多关于模块的信息请参考这里
注意 - 这不是一个确切的答案,而是对你的问题的梗概。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接