在 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);
}
}
所以我需要通过 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);
}
}