Le routage Angular2 peut activer et AuthGuard (JWT) avec le paramètre rôle de l'utilisateur

Dans ce projet exaple avec l'authentification JWT nous voyons comment autoriser seulement les utilisateurs authentifiés à certaines routes:

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 },
];

je voudrais faire un pas de plus et aussi indiquer quel rôle de l'Utilisateur a 'accès' à route-mais je ne sais pas comment passer l'argument pour canActivate AuthGuard (src). Donc je voudrais obtenir quelque chose comme ceci (par exemple, j'ai deux rôles: Administrateur et Employé):

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

où mon AuthGuard pourrait regarder quelque chose comme ceci (où userRole(= Administrateur ou d'un Employé ou nulle) est passé en paramètre à 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;
  }
}

où JWT.utilisateur.le rôle est l'assistant qui lit le rôle de l'utilisateur stocké dans le JWT token. Est-il un moyen de faire quelque chose de similaire, comme au-dessus de l'idée?

37
demandé sur Kamil Kiełczewski 2016-07-15 21:19:54

3 réponses

CanActivate ne vous permettra pas de passer un userRole comme vous le souhaitez. https://github.com/angular/angular/blob/2.0.0-rc.4/modules/%40angular/router/src/interfaces.ts#L54

il est probablement préférable de faire des classes séparées pour chacun de vos cas de rôle d'utilisateur. C'est aussi ce que disent les documents officiels: https://angular.io/docs/ts/latest/api/router/index/CanActivate-interface.html

5
répondu cienki 2016-07-15 22:40:15

vous pouvez définir le

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

et puis c'est en canActivateRoleGuard:

canActivate(route: ActivatedRouteSnapshot,
    state: RouterStateSnapshot): boolean {

    let roles = route.data["roles"] as Array<string>;
    return (roles == null || roles.indexOf("the-logged-user-role") != -1);
}

je pense que cela pourrait être une autre façon de le faire au lieu de créer une garde pour chaque rôle. Je voudrais en fait prendre cette déroute car il nécessite moins de code et gère le problème très bien.

74
répondu Arman 2017-02-15 21:48:25

NOTE: applicable pour les angulaires-rc.4<

@KamilKiełczewski, @NikolayRusev,

  1. ajouté en route données supplémentaires avec tableau des routes:

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

et dans CanActivate vous pouvez obtenir path à partir du premier paramètre, cherchez le même chemin dans la config route et obtenez vos rôles décrits à partir des données:

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

bien sûr, il serait préférable d'éviter des propriétés privées, et vous pouvez, mais je ne me souviens pas comment je l'ai fait.

mais pour mes porposes Je l'ai redirigé de manière différente. Le grand inconvénient de cette approche, je veux dire pour la garde basée sur les rôles, est que chaque utilisateur avec des rôles différents peut voir toutes les routes si vous les rendez dans un composant automatiquement pas manuellement.

  1. vous pouvez étendre router-outlet
2
répondu Andrei Shostik 2017-06-13 22:59:35