如何使用canActivate()拦截路由,防止越权访问其他用户资料
实现方案
前提准备
你需要先封装全局身份认证服务,存储当前登录用户的可信ID,避免前端伪造,示例的AuthService代码如下:
// auth.service.ts import { Injectable } from '@angular/core'; @Injectable({ providedIn: 'root' }) export class AuthService { // 此处返回的用户ID需要是登录后从后端接口获取并缓存的可信值,不要直接取前端本地存储未校验的值 getCurrentUserId(): string | null { const user = JSON.parse(localStorage.getItem('loginUser') || 'null'); return user?.userId || null; } isLoggedIn(): boolean { return !!this.getCurrentUserId(); } }
第一步:创建canActivate路由守卫
// user-access.guard.ts import { Injectable } from '@angular/core'; import { CanActivate, ActivatedRouteSnapshot, RouterStateSnapshot, Router } from '@angular/router'; import { AuthService } from './auth.service'; @Injectable({ providedIn: 'root' }) export class UserAccessGuard implements CanActivate { constructor( private authService: AuthService, private router: Router ) {} canActivate( route: ActivatedRouteSnapshot, state: RouterStateSnapshot ): boolean { // 1. 先校验用户是否登录 if (!this.authService.isLoggedIn()) { this.router.navigate(['/login']); return false; } // 2. 从路由参数中获取要访问的目标用户ID const targetUserId = route.paramMap.get('id'); // 3. 获取当前登录用户的ID const currentUserId = this.authService.getCurrentUserId(); // 4. 比对ID,一致则放行 if (targetUserId === currentUserId) { return true; } // 5. 不一致则拦截,跳转到403无权限页或者首页 this.router.navigate(['/403']); return false; } }
第二步:绑定守卫到目标路由
在你的路由配置文件中,给需要保护的用户资料/编辑路由添加守卫:
// app-routing.module.ts import { NgModule } from '@angular/core'; import { RouterModule, Routes } from '@angular/router'; import { UserEditComponent } from './user-edit/user-edit.component'; import { UserAccessGuard } from './user-access.guard'; const routes: Routes = [ // 其他路由... { path: 'user/:id/edit', component: UserEditComponent, canActivate: [UserAccessGuard] // 绑定守卫 } ]; @NgModule({ imports: [RouterModule.forRoot(routes)], exports: [RouterModule] }) export class AppRoutingModule { }
注意事项
- 前端路由守卫只能做第一层拦截,后端对应接口必须也要做相同的用户权限校验,避免攻击者绕过前端直接调用接口获取数据
- 存储在前端的登录用户ID建议配合JWT校验,不要直接使用未经验证的本地存储值,防止用户手动修改本地存储伪造身份
内容的提问来源于stack exchange,提问作者Tommy Gordon
相关产品推荐
相关产品推荐

