Как вы управляете ролями пользователей и разрешениями с помощью Angular 2

Я работаю над новым приложением Angular2, и мне было интересно, как вы управляете маршрутами, доступными для определенных ролей и разрешений для создания, редактирования и удаления элементов для определенных ролей.

Я хочу знать, как решить эту проблему:

  • Как вы управляете доступом к некоторым элементам пользовательского интерфейса? Как приложение знает, чтобы показать или скрыть это? Используете ли вы один сервис для этого? Или вы создаете разные условия для разных мест в своем приложении?

  • Как вы управляете своей маршрутизацией? Используете ли вы CanActivate, CanActivateChild, CanLoad и т.д.? Вы строите единую охранную службу для всех маршрутов или создаете разные службы для разных модулей или компонентов?

  • И последний вопрос. Каков наилучший способ разделить приложение, тогда вы можете продать его, как CMS? Я имею в виду, как мы можем реализовать возможность загрузки некоторых других модулей с рынка, например, и добавить их в ваше приложение?

Как вы решаете подобную проблему?

Любое руководство, опыт или указатели на материалы, посвященные этим темам, высоко оценены. Заранее спасибо.

Ответ 1

Как уже упоминалось в комментариях к вашему вопросу, полный ответ выходит за рамки вопроса/ответа SO, и поэтому вы можете в ближайшем будущем закрыть свой вопрос в ближайшем будущем, но вот несколько быстрых предложений для вас исследовать дальше самостоятельно:

  • Получите разрешения пользователя с сервера во время/после входа через http/https. Храните эти разрешения где-то, что имеет смысл для вашего приложения, возможно, в службе. Если вы используете JWT, разрешения могут быть возвращены в токере JWT.

  • Чтобы упростить ситуацию, разрешайте только разрешения на клиенте. Роли для кода сервера, чтобы выяснить, какие разрешения у пользователя есть. Не нужно гадости, объединяя роли с разрешениями на клиенте.

  • Защита маршрутов с помощью auth-охранников

  • Защитите отдельные элементы пользовательского интерфейса с помощью * ngIf или ngSwitch/* ngSwitchCase

  • Динамическая загрузка - большая область темы - прочитайте об этом - много ресурсов в Интернете. Однако, насколько я знаю, хотя вы можете лениво загружать модули, они должны быть известны приложению во время компиляции. Возможно, я ошибаюсь, но я не думаю, что вы можете просто загружать все, что захотите, во время выполнения.

Ответ 2

Поэтому мне пришлось реализовать что-то подобное в приложении, которое я разработал, вот как я его обработал.

Я создал службу auth, в которой содержался метод, который был проверен: пользователь имел роль управления:

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');
}

Я создал auth guard следующим образом:

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 { }

Затем я использовал защитник для моего маршрута, который обрабатывает навигацию в разделе admin

приложение-routing.module.ts

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

В моей навигационной панели я просто вызываю метод isManager и сохраняю его на переменной и использую, чтобы определить, нужно ли отображать ссылку управления или нет.

navbar.component.ts

public isManager: boolean = false;

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

navbar.component.html

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

Мне пришлось удалить некоторые данные из каждого метода, но это даст вам основную идею. Надеюсь, это поможет.

Ответ 3

Этот вопрос довольно широк, и я не уверен, что вы можете легко его покрыть в этом ответе. В нем есть три вещи

  • маршрутизация
  • гвардия
  • Модули

У вас должен быть один модуль защиты, который будет проверять все приложение, и все вспомогательные маршруты будут дочерними для маршрута охраны. Короче говоря, он будет действовать как глобальная охрана для всего вашего приложения. И ваша маршрутизация будет покрыта коротким. Подробнее о гвардии

И теперь, говоря о модулях, вам нужно разделить все на обычные и функциональные модули и повторно использовать модули или использовать их самостоятельно. Это поможет вам продать его, как CMS. Подробнее о модулях.

Примечание. Это не точный ответ, а суть проблемы.