Angular+Laravel开发:如何在前端存储权限以控制菜单显示?
在Angular SPA中结合Laravel Sanctum与Spatie Permissions实现权限控制
1. 后端调整:登录接口返回用户权限/角色
在Laravel登录逻辑中,验证用户成功后,将用户的权限(或角色)一并返回给前端。基于Spatie Permissions可以这样实现:
// 登录控制器示例代码 public function login(Request $request) { if (!Auth::attempt($request->only('email', 'password'))) { return response()->json(['message' => 'Invalid credentials'], 401); } $user = Auth::user(); // 获取用户所有权限(Spatie内置方法) $permissions = $user->getAllPermissions()->pluck('name')->toArray(); // 也可以获取用户所属角色 $roles = $user->getRoleNames()->toArray(); return response()->json([ 'token' => $user->createToken('auth_token')->plainTextToken, 'permissions' => $permissions, 'roles' => $roles ]); }
2. 前端修改AuthService:存储权限并添加判断方法
更新你的Angular AuthService,在登录时同步存储权限信息,并封装权限检查方法:
import { Injectable } from '@angular/core'; import { HttpClient } from '@angular/common/http'; import { Observable } from 'rxjs'; import { map } from 'rxjs/operators'; import { Router } from '@angular/router'; @Injectable({ providedIn: 'root' }) export class AuthService { private baseURL = "http://localhost:8000/api"; constructor(private http: HttpClient, public router: Router) { } login(username: string, password: string): Observable<boolean> { return this.http.post<{token: string, permissions: string[], roles: string[]}>(this.baseURL+'/login', {email: username, password: password}) .pipe( map(result => { localStorage.setItem('access_token', result.token); // 将权限和角色转为JSON字符串存储到localStorage localStorage.setItem('user_permissions', JSON.stringify(result.permissions)); localStorage.setItem('user_roles', JSON.stringify(result.roles)); return true; }) ); } getToken() { return localStorage.getItem('access_token'); } // 获取用户权限列表 getPermissions(): string[] { const permissions = localStorage.getItem('user_permissions'); return permissions ? JSON.parse(permissions) : []; } // 获取用户角色列表 getRoles(): string[] { const roles = localStorage.getItem('user_roles'); return roles ? JSON.parse(roles) : []; } // 检查是否拥有指定权限 hasPermission(permission: string): boolean { return this.getPermissions().includes(permission); } // 检查是否拥有指定角色 hasRole(role: string): boolean { return this.getRoles().includes(role); } logout() { // 清除所有认证相关存储 localStorage.removeItem('access_token'); localStorage.removeItem('user_permissions'); localStorage.removeItem('user_roles'); this.router.navigate(['login']); } public get isLoggedIn(): boolean { // 建议补充token过期校验,比如解析JWT判断有效期 return localStorage.getItem('access_token') !== null; } }
3. 前端控制菜单显示
在菜单组件中,使用*ngIf结合AuthService的方法来控制菜单的显示隐藏:
<!-- 侧边栏菜单示例 --> <ul class="sidebar-menu"> <li *ngIf="authService.isLoggedIn"> <a routerLink="/dashboard">控制台</a> </li> <!-- 仅拥有manage_users权限的用户可见 --> <li *ngIf="authService.hasPermission('manage_users')"> <a routerLink="/users">用户管理</a> </li> <!-- 仅admin角色的用户可见 --> <li *ngIf="authService.hasRole('admin')"> <a routerLink="/settings">系统设置</a> </li> </ul>
记得在组件中注入AuthService:
import { AuthService } from '../services/auth.service'; @Component({ selector: 'app-sidebar', templateUrl: './sidebar.component.html' }) export class SidebarComponent { constructor(public authService: AuthService) {} }
4. 关键注意事项
- 前端控制仅为UI层面:绝对不能依赖前端权限控制保护API接口,后端必须在每个需要授权的接口中使用Spatie Permissions中间件或Laravel Gates做校验,示例:
// 路由示例 Route::get('/users', [UserController::class, 'index'])->middleware('permission:manage_users'); - 权限更新同步:如果后端用户权限发生变化,前端需要重新获取最新权限(比如用户重新登录,或提供专门的刷新权限接口)。
- 存储安全性:若担心localStorage的风险,可改用sessionStorage,或结合Angular服务变量+路由守卫,但后者刷新页面后会丢失权限数据,建议搭配localStorage使用同时确保全站HTTPS传输。
内容的提问来源于stack exchange,提问作者Kennedy Mwenda
相关产品推荐
相关产品推荐

