簡體   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