[英]Guard for restricting user access to specific routes in angular not working
我试图根据用户角色限制用户对特定路由的访问。 我已经创建了一个新的角色守卫来执行此操作,但仍然能够访问受限制的路线。提前感谢您的帮助
这是我的后卫:
export class RoleGuard implements CanActivate {
role: string;
constructor(private router: Router) { }
canActivate(
next: ActivatedRouteSnapshot,
state: RouterStateSnapshot): Observable<boolean | UrlTree> | Promise<boolean | UrlTree> | boolean | UrlTree {
this.getRole().subscribe(data => {
this.role = data;
});
const userRole = JSON.parse(localStorage.getItem('user_role'));
if (userRole === 'admin'&& this.role === 'ADMIN') {
// role not authorised so redirect to home page
this.router.navigate(['']);
return false;
}
else {
return true;
}
}
getRole(): Observable<any> {
return this.router.events.pipe(map(data => {
if (data instanceof ChildActivationStart) {
return data.snapshot.data.roles;
}
}));
}
}
当我尝试在警卫中记录角色时,我可以看到在初始管理值之后的值未定义,这意味着 canActivate 被多次调用,但 getRole 方法只被调用一次。 这是我的路由模块:
const routes: Routes = [{
path: '',
pathMatch: 'prefix',
component: AppComponent,
canActivate: [AuthGuard],
children: [
{
path: 'admin',
canActivate: [RoleGuard],
data: {
title: 'Admin Support',
roles: 'ADMIN'
},
loadChildren: () => import('./admin/admin.module').then(m => m.AdminModule)
},
{
path: 'user',
loadChildren: () => import('./user/user.module').then(m => m.UserModule)
}
],
}
您正在订阅一个 observable,但是当您检查它的值时它已经退出了该方法。
当你点击this.role === 'ADMIN'
this.role 等于undefined
你应该从这个方法返回一个 Observable
canActivate(
next: ActivatedRouteSnapshot,
state: RouterStateSnapshot): Observable<boolean> {
return this.getRole().pipe(map(role => {
const userRole = JSON.parse(localStorage.getItem('user_role'));
if (userRole === 'admin' && role === 'ADMIN') {
// role not authorised so redirect to home page
this.router.navigate(['']);
return false;
}
else {
return true;
}));
}
getRole(): Observable<string> {
return this.router.events.pipe(map(data => {
if (data instanceof ChildActivationStart) {
return data.snapshot.data.roles as string;
}
}));
}
一般而言,您应该更多地研究可观察对象的工作原理
正如我所说,问题是您在订阅内返回,而返回值永远不会超出订阅。 The idea behind the Angular Guard is that it should inform the router whether or not the navigation is allowed, so the Guard must return something ideally a boolean or an Observable or a Promise that resolves to boolean.
考虑到这一点,看看下面的方法,它可能无法通过简单的复制粘贴来工作,但应该可以帮助你走上正轨。
export class RoleGuard implements CanActivate {
role: string;
constructor(private router: Router) {}
canActivate(
next: ActivatedRouteSnapshot,
state: RouterStateSnapshot
): Observable<boolean | UrlTree> | Promise<boolean | UrlTree> | boolean | UrlTree {
return this.router.events.pipe(
filter((event: RouterEvent) => event instanceof ChildActivationStart),
// use the tap for debugging purposes (I'm not sure if ChildActivationStart will contain what your are looking for)
tap((event) => console.log(event)),
map((event: any) => event.snapshot.data.roles),
map((role: string) => this.isUserAuthorized(role)),
tap((authorized: boolean) => {
if (!authorized) { this.router.navigate(['']); }
})
);
}
private isUserAuthorized(role: string): boolean {
try {
// JSON.parse might fail, it's a good practice to catch the errors
const userRole = JSON.parse(localStorage.getItem('user_role'));
return userRole === 'admin' && role === 'ADMIN';
} catch (e) {
return false;
}
}
}
不要放弃并发布任何进一步的错误。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.