在 Angular Guard 上使用 window.location 的无限循环

Infinite loop using window.location on an Angular Guard

所以我需要通过 JWT 基于用户角色启动这个 Angular13 应用程序。 如果用户是“超级组织者”,那么我需要呈现某个视图,但如果用户是“组织者”,那么我需要呈现另一个视图。

经过一些研究,我尝试使用 Angular 的 canActivate Guard,它很成功,但我现在遇到了问题:

如果用户不是“超级组织者”,我会遇到无限循环,因为使用“window.location.href”进行重定向。

我找了很多解决方案,但无法解决我的问题。

这是我的 AuthService:

import { UserModel } from '../models/user.model';

@Injectable({
  providedIn: 'root'
})
export class AuthService {

  // superorganizer: string = "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpZCI6ImZlZHBhdDAxIiwibmFtZSI6Ik5pY28gQWx2YXJleiIsInJvbGUiOiJzdXBlcm9yZ2FuaXplciJ9.qsWFtsv8mA0gpqF_JFmMVNZyT9QptkrUnjmhIA-KGDI"

  user!: UserModel;
  hardcodedJWT: string = "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpZCI6ImZlZHBhdDAxIiwibmFtZSI6Ik5pY28gQWx2YXJleiIsInJvbGUiOiJvcmdhbml6ZXIifQ.6ppbCs-_L2aUVfTiz5ONIVTBP8H9ON2u9CGjpZnWzsE"



  constructor() { }
 
  getUser(): UserModel {
   this.user = JSON.parse(atob(this.hardcodedJWT.split('.')[1]));
   console.log(this.user);
   return this.user;
  }
}

这是我的守卫:

import { ActivatedRouteSnapshot, CanActivate, CanLoad, Route, RouterStateSnapshot, UrlSegment, UrlTree } from '@angular/router';
import { Observable } from 'rxjs';
import { AuthService } from '../services/auth.service';

@Injectable({
  providedIn: 'root'
})
export class AuthGuard implements CanActivate {

  constructor(private authService: AuthService) { }

  canActivate(
    route: ActivatedRouteSnapshot,
    state: RouterStateSnapshot): Observable<boolean | UrlTree> | Promise<boolean | UrlTree> | boolean | UrlTree {
      this.authService.getUser();
      if(!this.authService.user.role.includes('superorganizer') ) {
       window.location.href='http://localhost:4200/organizer';
        
      }
      return this.authService.user.role.includes(route.data.role);
  }
}

最后,这是我的应用程序-routing.module:

import { Routes, RouterModule } from '@angular/router';
import { OrganizerComponent } from './organizer/organizer.component';
import { SuperOrganizerComponent } from './super-organizer/super-organizer.component';
import { AuthGuard } from './guards/auth.guard';

const routes: Routes = [

  {
    path: '',
    component: SuperOrganizerComponent,
    canActivate: [AuthGuard],
    data: {
      role: 'superorganizer'
    }
  },
  {
    path: 'organizer',
    component: OrganizerComponent,
    canActivate: [AuthGuard],
    data: {
      role: 'organizer'
    }
  },
  {
    path: '**',
    redirectTo: '',
  }

]


@NgModule({
  imports: [
    RouterModule.forRoot(routes)
  ],
  exports: [RouterModule]
})
export class AppRoutingModule { }

提前感谢您对此问题的任何想法

您应该通过路由器服务更改url,而不是直接在浏览器中通过url更改,代码示例如下:

export class AuthGuard implements CanActivate {

  constructor(private authService: AuthService) { }

  canActivate(
    route: ActivatedRouteSnapshot,
    router: Router,
    state: RouterStateSnapshot
  ) {
      this.authService.getUser();

      if(!this.authService.user.role.includes('superorganizer') ) {
        this.router.navigateByUrl('/organizer');
        return false;
      }

      return this.authService.user.role.includes(route.data.role);
  }
}