具有用户角色参数的 Angular2 路由 canActivate 和 AuthGuard (JWT)
Angular2 routing canActivate and AuthGuard (JWT) with user role parameter
在这个exaple project 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 },
];
我想更进一步,并指出哪些用户角色有 'access' 路由 - 但我不知道如何将参数传递给 canActivate AuthGuard (src)。所以我想实现这样的目标(例如我有两个角色:管理员和员工):
{ 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 令牌中的用户角色的助手。有没有办法做类似上述想法的事情?
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
注意:适用于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;
}
当然最好避免私有属性,你可以,但我不记得我是如何做到的。
但为了我的目的,我以不同的方式重做了它。这种方法的巨大缺点,我指的是基于角色的守卫,是每个具有不同角色的用户都可以看到所有的路由,如果你在一个组件中自动渲染它们而不是手动的话。
你可以这样设置路由的data
参数
const appRoutes: Routes = [
{
path: 'account/super-secure',
component: SuperSecureComponent,
canActivate: [RoleGuard],
data: { roles: ['super-admin', 'admin'] }
}];
然后将其放入 RoleGuard
的 canActivate
中:
canActivate(route: ActivatedRouteSnapshot,
state: RouterStateSnapshot): boolean {
let roles = route.data["roles"] as Array<string>;
return (roles == null || roles.indexOf("the-logged-user-role") != -1);
}
我认为这可能是另一种方式,而不是为每个角色创建守卫。我实际上会采用这种方法,因为它需要更少的代码并且可以很好地处理问题。
在这个exaple project 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 },
];
我想更进一步,并指出哪些用户角色有 'access' 路由 - 但我不知道如何将参数传递给 canActivate AuthGuard (src)。所以我想实现这样的目标(例如我有两个角色:管理员和员工):
{ 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 令牌中的用户角色的助手。有没有办法做类似上述想法的事情?
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
注意:适用于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;
}
当然最好避免私有属性,你可以,但我不记得我是如何做到的。
但为了我的目的,我以不同的方式重做了它。这种方法的巨大缺点,我指的是基于角色的守卫,是每个具有不同角色的用户都可以看到所有的路由,如果你在一个组件中自动渲染它们而不是手动的话。
你可以这样设置路由的data
参数
const appRoutes: Routes = [
{
path: 'account/super-secure',
component: SuperSecureComponent,
canActivate: [RoleGuard],
data: { roles: ['super-admin', 'admin'] }
}];
然后将其放入 RoleGuard
的 canActivate
中:
canActivate(route: ActivatedRouteSnapshot,
state: RouterStateSnapshot): boolean {
let roles = route.data["roles"] as Array<string>;
return (roles == null || roles.indexOf("the-logged-user-role") != -1);
}
我认为这可能是另一种方式,而不是为每个角色创建守卫。我实际上会采用这种方法,因为它需要更少的代码并且可以很好地处理问题。