Angular - 如何结合 AuthGuard 和 RoleGuard
Angular - How to combine AuthGuard and RoleGuard
在Angular-13项目中我有三个角色:Admin、Teacher和Student。用户只能有一个角色。
我有响应如下所示的用户模型:
user.ts:
export interface IResponse<T> {
message: string;
code: number;
results: T;
}
export interface IUser {
token?: string;
roles?: string[];
}
授权服务:
export class AuthService {
baseUrl = environment.apiUrl;
constructor(private http: HttpClient, private router: Router) { }
login(model: any){
return this.http.post<IResponse<IUser>>(this.baseUrl+'auth/login', model).pipe(
tap((response)=>{
const user = response.results;
return user;
})
)
}
getToken(): string | null {
return localStorage.getItem('token');
}
isLoggedIn() string | null {
return this.getToken();
}
}
当用户登录时,令牌和角色存储在本地存储中。此外,用户会根据角色重定向到仪表板。
login.component:
login(){
this.authService.login(this.loginForm.value).subscribe({
next: (res: any) => {
if (res.result.roles[0] == 'Admin'){
this .router.vavigateByUrl('/admin-dashboard');
} else if (res.result.roles[0] == 'Teacher'){
this .router.vavigateByUrl('/teacher-dashboard');
}else {
this .router.vavigateByUrl('student-dashboard');
}
localStorage.setItem('token', JSON.stringify(res.result.token));
localStorage.setItem('role', JSON.stringify(res.result.role[0]));
}
})
}
auth.guards:
export class AuthGuard implements CanActivate {
constructor(private authService: AuthService, private toastr: ToastrService, private router: Router) { }
canActivate(route: ActivateRouteSnapshot, state: RouterStateSnapshot): Observable<boolean> {
if (!this.authService.isLoggedIn()) {
this.toastr.info('Please Log In');
this.router.navigate(['/login']);
return false;
}
this.authService.isLoggedIn()
return true
}
}
应用-routing.module:
const routes: Routes = [
{path: '', redirectTo: 'login', pathMatch: 'full'},
{path: 'teacher-dashboard', canActivate: [AuthGuard], loadChildren: () => import('./feature/teacher/teacher.module').then(m => m.TeacherModule)},
{path: 'login', loadChildren: () => import('./feature/login/login.module').then(m => m.AuthModule)},
{path: 'student-dashboard', canActivate: [AuthGuard], loadChildren: () => import('./feature/student/student.module').then(m => m.StudentModule)},
{path: 'admin-dashboard', canActivate: [AuthGuard], loadChildren: () => import('./feature/admin/admin.module').then(m => m.AdminModule)},
];
如上所示,我已经用AuthGuard保护了路由。我如何仍然使用 Role 保护路由,以便学生不会到达教师仪表板、管理员仪表板,反之亦然?
谢谢
canActivate 接受一组守卫。所以你的 RoleGuard
可以添加到 AuthGuard 旁边,你应该可以开始了。
{path: 'teacher-dashboard', canActivate: [AuthGuard, RoleGuard], loadChildren: () => import('./feature/teacher/teacher.module').then(m => m.TeacherModule)}
由于守卫是串行执行的,因此您的 RoleGuard 可以简单地获取有关登录用户的角色信息并进行相应的重定向。
role.guard.ts
canActivate(): boolean {
if (localStorage.get('role') === 'teacher') {
return true;
}
return this.router.navigate('some other url');
}
仅供参考,您将两个项目设置为相同的键:
localStorage.setItem('token', JSON.stringify(res.result.token));
localStorage.setItem('token', JSON.stringify(res.result.role[0])); // make it 'role'
在Angular-13项目中我有三个角色:Admin、Teacher和Student。用户只能有一个角色。
我有响应如下所示的用户模型:
user.ts:
export interface IResponse<T> {
message: string;
code: number;
results: T;
}
export interface IUser {
token?: string;
roles?: string[];
}
授权服务:
export class AuthService {
baseUrl = environment.apiUrl;
constructor(private http: HttpClient, private router: Router) { }
login(model: any){
return this.http.post<IResponse<IUser>>(this.baseUrl+'auth/login', model).pipe(
tap((response)=>{
const user = response.results;
return user;
})
)
}
getToken(): string | null {
return localStorage.getItem('token');
}
isLoggedIn() string | null {
return this.getToken();
}
}
当用户登录时,令牌和角色存储在本地存储中。此外,用户会根据角色重定向到仪表板。
login.component:
login(){
this.authService.login(this.loginForm.value).subscribe({
next: (res: any) => {
if (res.result.roles[0] == 'Admin'){
this .router.vavigateByUrl('/admin-dashboard');
} else if (res.result.roles[0] == 'Teacher'){
this .router.vavigateByUrl('/teacher-dashboard');
}else {
this .router.vavigateByUrl('student-dashboard');
}
localStorage.setItem('token', JSON.stringify(res.result.token));
localStorage.setItem('role', JSON.stringify(res.result.role[0]));
}
})
}
auth.guards:
export class AuthGuard implements CanActivate {
constructor(private authService: AuthService, private toastr: ToastrService, private router: Router) { }
canActivate(route: ActivateRouteSnapshot, state: RouterStateSnapshot): Observable<boolean> {
if (!this.authService.isLoggedIn()) {
this.toastr.info('Please Log In');
this.router.navigate(['/login']);
return false;
}
this.authService.isLoggedIn()
return true
}
}
应用-routing.module:
const routes: Routes = [
{path: '', redirectTo: 'login', pathMatch: 'full'},
{path: 'teacher-dashboard', canActivate: [AuthGuard], loadChildren: () => import('./feature/teacher/teacher.module').then(m => m.TeacherModule)},
{path: 'login', loadChildren: () => import('./feature/login/login.module').then(m => m.AuthModule)},
{path: 'student-dashboard', canActivate: [AuthGuard], loadChildren: () => import('./feature/student/student.module').then(m => m.StudentModule)},
{path: 'admin-dashboard', canActivate: [AuthGuard], loadChildren: () => import('./feature/admin/admin.module').then(m => m.AdminModule)},
];
如上所示,我已经用AuthGuard保护了路由。我如何仍然使用 Role 保护路由,以便学生不会到达教师仪表板、管理员仪表板,反之亦然?
谢谢
canActivate 接受一组守卫。所以你的 RoleGuard
可以添加到 AuthGuard 旁边,你应该可以开始了。
{path: 'teacher-dashboard', canActivate: [AuthGuard, RoleGuard], loadChildren: () => import('./feature/teacher/teacher.module').then(m => m.TeacherModule)}
由于守卫是串行执行的,因此您的 RoleGuard 可以简单地获取有关登录用户的角色信息并进行相应的重定向。
role.guard.ts
canActivate(): boolean {
if (localStorage.get('role') === 'teacher') {
return true;
}
return this.router.navigate('some other url');
}
仅供参考,您将两个项目设置为相同的键:
localStorage.setItem('token', JSON.stringify(res.result.token));
localStorage.setItem('token', JSON.stringify(res.result.role[0])); // make it 'role'