繁体   English   中英

用于限制用户访问 angular 中特定路由的防护不起作用

[英]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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM