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