Подтвердить что ты не робот

Angular2 маршрутизация canActivate и AuthGuard (JWT) с параметром роли пользователя

В этом проекте exaple с проверкой подлинности JWT мы можем разрешить доступ только определенным пользователям на определенный маршрут:

import { RouterConfig } from '@angular/router';
import { Home } from './home';
import { Login } from './login';
import { Signup } from './signup';
import { AuthGuard } from './common/auth.guard';

export const routes: RouterConfig = [
  { path: '',       component:  Login },
  { path: 'login',  component: Login },
  { path: 'signup', component: Signup },
  { path: 'home',   component: Home, canActivate: [AuthGuard] },
  { path: '**',     component: Login },
];

Я хотел бы сделать шаг дальше, а также указать, какая роль пользователя имеет "доступ" к маршруту, но я не знаю, как передать аргумент canActivate AuthGuard (src). Поэтому я хотел бы добиться чего-то подобного (например, у меня есть две роли: Admin and Employee):

  { path: 'home',   component: Home, canActivate: [AuthGuard] },
  { path: 'users',   component: AdminUsers, canActivate: [AuthGuard('Admin')] },
  { path: 'users',   component: Employees, canActivate: [AuthGuard('Employee')] },

Где мой AuthGuard может выглядеть примерно так (где userRole (= Admin или Employee или null) передается параметру AuthGuard):

@Injectable()
export class AuthGuard implements CanActivate {
  constructor(private router: Router) {}

  canActivate(userRole) {
    if (!userRole || JWT.user().role == userRole) {
      return true;
    }

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

где JWT.user.role - это помощник, который считывает роль пользователя, хранящуюся в токере JWT. Есть ли способ сделать что-то подобное, как идея выше?

4b9b3361

Ответ 1

Подпись для CanActivate не позволит вам передать userRole, как вы хотите. https://github.com/angular/angular/blob/2.0.0-rc.4/modules/%40angular/router/src/interfaces.ts#L54

Вероятно, лучше всего делать отдельные классы для каждого из ваших случаев роли пользователя. Это руководство в официальных документах также: https://angular.io/docs/ts/latest/api/router/index/CanActivate-interface.html

Ответ 2

Вы можете установить параметр data маршрута с такой ролью

const appRoutes: Routes = [
{ 
  path: 'account/super-secure', 
  component: SuperSecureComponent, 
  canActivate: [RoleGuard], 
  data: { roles: ['super-admin', 'admin'] } 
}];

Ответ 3

ПРИМЕЧАНИЕ: применимо для angular -rc.4 <

@KamilKiełczewski, @NikolayRusev,

  • добавлено в маршрут дополнительные данные с массивом маршрутов:

...
{
    path: "customers",
    component: CustomersCmp,
    data: { roles: ["admin"] }
},
...

а в CanActivate вы можете получить path из первого параметра, найти один и тот же путь в конфигурации маршрута и получить свои описанные роли из данных:

public canActivate(route: ActivatedRouteSnapshot): boolean {
    let path = route._urlSegment.pathsWithParams[0].path;
    let roles;

    if (route._routeConfig.path == path) {
        roles = route._routeConfig.data.roles
    } else {
        roles = route._routeConfig.children.find(_route => _route.path == path).data.roles;
    }

    if (...) {
        return true;
    }

    return false;
}

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

Но для моих приемов я переделал его по-другому. Огромный недостаток этого подхода, я имею в виду для защиты на основе ролей, состоит в том, что каждый пользователь с разными ролями может видеть все маршруты, если вы автоматически их рендерите в компоненте вручную.

  1. вы можете расширить router-outlet