route canactivate authguard auth activate javascript authentication angular roles angular2-routing

javascript - canactivate - authguard roles



El enrutamiento Angular2 puede activar y AuthGuard(JWT) con un parámetro de rol de usuario (3)

En este proyecto de exaple con autenticación JWT, vemos cómo permitir solo a los usuarios autenticados alguna ruta:

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

Me gustaría dar un paso más y también indicar qué función de usuario tiene ''acceso'' a la ruta, pero no sé cómo pasar argumentos a canActivate AuthGuard (src) . Así que me gustaría lograr algo como esto (por ejemplo, tengo dos roles: administrador y empleado):

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

Donde mi AuthGuard podría verse algo así (donde userRole (= Admin o Employee o null) pasa el parámetro a 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; } }

donde JWT.user.role es helper, que lee el rol de usuario almacenado en el token JWT. ¿Hay alguna manera de hacer algo similar a la idea anterior?



Puede establecer el parámetro de data de la ruta con el rol como este

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

y luego tener esto en canActivate de RoleGuard :

canActivate(route: ActivatedRouteSnapshot, state: RouterStateSnapshot): boolean { let roles = route.data["roles"] as Array<string>; return (roles == null || roles.indexOf("the-logged-user-role") != -1); }

Creo que esta podría ser otra forma de hacerlo en lugar de crear guardia para cada función. De hecho tomaría esta ruta ya que requiere menos código y maneja el problema muy bien.


NOTA : aplicable para angular-rc.4 <

@ KamilKiełczewski, @NikolayRusev,

  1. Se agregaron datos adicionales en ruta con una matriz de rutas:

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

y en CanActivate puede obtener la path desde el primer parámetro, buscar la misma ruta en la configuración de la ruta y obtener las funciones descritas de los datos:

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

Por supuesto, sería mejor evitar las propiedades privadas, y puedes, pero no recuerdo cómo lo hice exactamente.

Pero para mis propósitos, lo rehice de otra manera. La gran desventaja de este enfoque, me refiero a la protección basada en roles, es que cada usuario con roles diferentes puede ver todas las rutas si las representa en un componente automáticamente y no manualmente.

  1. puedes extender router-outlet