CanActivateGuard и передача данных в Guard

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

Вот охранник:

 export class AuthenticatedGuard implements CanActivate
    {
        constructor (private memSrv:MembershipService,
private themeSrv:ThemeService,private router:Router )
        {
        }
        canActivate(
            route: ActivatedRouteSnapshot,
            state: RouterStateSnapshot
        ): Observable<boolean> | Promise<boolean> | boolean {

            return this.memSrv.GetCurrentUser()
                .map(u => {
                    if (!u) {
                        this.router.navigate([this.themeSrv.LoginUrl]);
                        return false;
                    }
                    var isAuth = u.Capabilities.some(s => s === this.themeSrv.AuthCapability);
                    if (isAuth) {
                        return true;
                    }
                    else {
                        //TODO: This is an unauthorized but authenticated user it should go to an unauthorized page
                        this.router.navigate(["/Unauthorized", { url: state.url }]);
                        return false;
                    }
                }
                );


        }
    }

Теперь у меня есть модуль с некоторыми маршрутами, которые необходимо защитить с помощью другой роли. Мой вопрос заключается в том, как я могу передать AuthenticationGuard роль, которую необходимо проверять для каждого маршрута. Мне не хотелось бы создавать разных охранников для каждой роли, которую мы хотим проверить.

Ниже приведен фрагмент конфигурации моего маршрута.

   {
        path: "",
        component: Component.MainComponent, 
        children:
        [
            {
                path: 'attachmentsTest',
                component: Component.AttachmentsTestComponent,
            },
            {
                path:"home",
                component: Component.HomeComponent,
                canActivate: [AuthenticatedGuard],
                resolve: {
                    user: CurrentUserResolver
                }
            }, 

person JoshBerke    schedule 22.01.2018    source источник
comment
Не могли бы вы установить его в свойстве данных маршрута?   -  person DeborahK    schedule 23.01.2018
comment
Вы можете поместить роль в localStorage при изменении маршрута и получить ее в режиме охраны?   -  person Powkachu    schedule 23.01.2018
comment
@DeborahK не уверен, можете ли вы указать значения в конфигурации маршрута, чтобы вытащить последний, если это сработает   -  person JoshBerke    schedule 23.01.2018
comment
Вы можете прочитать текущий маршрут и решить, какую роль нужно проверить. Но я не думаю, что это будет лучшей практикой. На мой взгляд, использование Guard для каждой роли было бы лучшей практикой. и если есть похожий код, который вы не хотите копировать, вы можете поместить их либо в общий Guard, который будет вызываться в родительском маршруте, либо во внешнем сервисе.   -  person Samy Sammour    schedule 23.01.2018
comment
@SamySammour да, но в настоящее время у нас есть около 30 различных ролей, от которых нужно защититься, и этот список постоянно растет. Если бы нас было немного, это было бы одно...   -  person JoshBerke    schedule 23.01.2018
comment
Ну, это очень интересный вопрос с множеством сценариев. Я еще раз подумаю завтра и немного поищу, и я напишу вам, если что-то новое придет в голову.   -  person Samy Sammour    schedule 24.01.2018
comment
У меня есть только идея, я не уверен, что это решит проблему, но это может привести к чему-то. Я думаю о создании одного Guard и внедрении его в модуль с несколькими значениями, например. 30 провайдеров, и каждый имеет уникальное имя и уникальную роль. Но все они вызывают одного и того же охранника с разной информацией. Итак, One-Guard/Multi-Providers я проделывал тот же трюк в .NET Dependency Injection. Теоретически это может сработать!   -  person Samy Sammour    schedule 25.01.2018


Ответы (1)


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

@NgModule({
  imports: [
    RouterModule.forChild([
      { 
        path: 'products',
        component: ProductListComponent,
        data: { pageTitle: 'Product List' }
      },
      { path: 'products/:id', component: ProductDetailComponent },
      { path: 'products/:id/edit', component: ProductEditComponent }
    ])
  ],  // ...

Обратите внимание на свойство данных здесь.

Затем вы можете прочитать это свойство, используя такой синтаксис:

this.pageTitle = this.route.snapshot.data['pageTitle'];
person DeborahK    schedule 23.01.2018
comment
Считаете ли вы это лучшей практикой в ​​таком случае? Ну, на мой взгляд, было бы лучше сделать несколько охранников для каждой секции. безопасно ли использовать моментальный снимок маршрута для хранения роли? - person Samy Sammour; 23.01.2018
comment
Этот вопрос действительно зависит. Я недостаточно знаю об этом конкретном сценарии, чтобы определить, является ли он лучшим подходом. Но каждый раз, когда вам нужно дублировать очень похожий код, для меня это не лучшая практика, потому что обслуживание становится трудным. Там нет ничего плохого в определении бита данных с помощью свойства данных. - person DeborahK; 23.01.2018
comment
и поскольку я защищаю маршрут, мне кажется, что включение этих данных в маршрут имеет смысл. - person JoshBerke; 24.01.2018