Javascript 带有用户角色参数的 Angular2 路由 canActivate 和 AuthGuard (JWT)
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/38402776/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Angular2 routing canActivate and AuthGuard (JWT) with user role parameter
提问by Kamil Kie?czewski
In this exaple projectwith JWT authentication we se how to allow only authenticated users to some route:
在这个带有 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 },
];
I would like make step further and also indicate what user role have 'access' to route - but I don't know how to pass argument to canActivate AuthGuard (src). So I would like to achieve something like this (for instance I have two roles: Admin and Employee):
我想更进一步,并指出哪些用户角色可以“访问”路由 - 但我不知道如何将参数传递给 canActivate AuthGuard (src)。所以我想实现这样的目标(例如我有两个角色:管理员和员工):
{ path: 'home', component: Home, canActivate: [AuthGuard] },
{ path: 'users', component: AdminUsers, canActivate: [AuthGuard('Admin')] },
{ path: 'users', component: Employees, canActivate: [AuthGuard('Employee')] },
Where my AuthGuard could look something like this (where userRole(= Admin or Employee or null) is passed parameter to AuthGuard):
我的 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;
}
}
where JWT.user.role is helper which read user role stored in JWT token. Is there a way to do something similar like above idea?
其中 JWT.user.role 是读取存储在 JWT 令牌中的用户角色的助手。有没有办法做类似上面的想法?
采纳答案by cienki
The signature for CanActivate
won't allow you to pass a userRole
like you want to. https://github.com/angular/angular/blob/2.0.0-rc.4/modules/%40angular/router/src/interfaces.ts#L54
的签名CanActivate
不允许你传递userRole
你想要的。https://github.com/angular/angular/blob/2.0.0-rc.4/modules/%40angular/router/src/interfaces.ts#L54
It's probably best to do separate classes for each of your user role cases. That's the guidance in the official docs too: https://angular.io/docs/ts/latest/api/router/index/CanActivate-interface.html
最好为每个用户角色案例做单独的类。这也是官方文档中的指导:https: //angular.io/docs/ts/latest/api/router/index/CanActivate-interface.html
回答by Arman
You can set the data
parameter of the route with the role like this
您可以data
像这样设置路由的参数
const appRoutes: Routes = [
{
path: 'account/super-secure',
component: SuperSecureComponent,
canActivate: [RoleGuard],
data: { roles: ['super-admin', 'admin'] }
}];
and then have this in canActivate
of RoleGuard
:
再有这canActivate
的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);
}
I think this could be another way of doing it instead of creating guard for every role. I would actually take this rout since it requires less code and handles the problem very nicely.
我认为这可能是另一种方式,而不是为每个角色创建警卫。我实际上会采取这种方式,因为它需要更少的代码并且可以很好地处理问题。
回答by Andrei Shostik
NOTE: applicable for angular-rc.4 <
注意:适用于angular-rc.4 <
@KamilKie?czewski, @NikolayRusev,
@KamilKie?czewski、@NikolayRusev、
added in route additional data with array of routes:
在路由中添加了带有路由数组的附加数据:
...
{
path: "customers",
component: CustomersCmp,
data: { roles: ["admin"] }
},
...
and in CanActivate you can get path
from first parameter, search the same path in route config and get your described roles from data:
在 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;
}
Of course it would be better to avoid private properties, and you can, but I cannot remember how I exactly done it.
当然最好避免私有财产,你可以,但我不记得我是怎么做到的。
But for my porposes I redid it in different way. The huge disadvantage of this approach, I mean for role based guard, is that every user with different roles can see all of the routes if you render them in a component automatically not manually.
但是对于我的海豚,我以不同的方式重做了它。这种方法的巨大缺点,我的意思是对于基于角色的保护,如果你在组件中自动渲染它们而不是手动渲染,那么每个具有不同角色的用户都可以看到所有的路由。
- you can extend
router-outlet