在Symfony 5.4与React 18.16中实现Admin角色路由权限及Token传输
Symfony 5.4 + React 18.16 Token路由权限控制完整流程
这不是二选一的问题,后端(Symfony)和前端(React)需要配合完成权限控制,具体步骤如下:
一、Symfony后端处理
- 确保Token包含角色信息
你已经能在Postman拿到Token,现在要保证Token的payload里包含用户角色(比如ROLE_ADMIN)。如果用LexikJWTAuthenticationBundle,只需在User实体的getRoles()方法返回正确角色数组,Bundle会自动把角色加入JWT payload。 - 保护后端API路由
在config/packages/security.yaml里配置权限规则,限制Admin角色才能访问特定接口:
非Admin角色的请求访问security: # 其他配置... access_control: - { path: ^/api/admin, roles: ROLE_ADMIN } - { path: ^/api/public, roles: IS_AUTHENTICATED_ANONYMOUSLY }/api/admin路径时,会直接返回403权限错误。 - 可选:统一权限异常处理
可以创建一个异常监听器,把Symfony的权限异常转换成JSON格式响应,方便前端处理:
不需要额外自定义控制器,Symfony自带的Security组件已经能完成权限校验。// src/EventListener/AuthenticationExceptionListener.php namespace App\EventListener; use Symfony\Component\HttpFoundation\JsonResponse; use Symfony\Component\HttpKernel\Event\ExceptionEvent; use Symfony\Component\Security\Core\Exception\AccessDeniedException; class AuthenticationExceptionListener { public function onKernelException(ExceptionEvent $event): void { $exception = $event->getThrowable(); if ($exception instanceof AccessDeniedException) { $response = new JsonResponse([ 'message' => '无权限访问此资源' ], 403); $event->setResponse($response); } } }
二、React前端处理
- 存储Token
登录请求成功后,把后端返回的Token存在localStorage或sessionStorage中:// 登录请求示例 const login = async (credentials) => { const response = await axios.post('/api/login', credentials); localStorage.setItem('authToken', response.data.token); }; - 全局请求拦截器
用Axios设置请求拦截器,给所有需要权限的请求自动带上Token:import axios from 'axios'; axios.interceptors.request.use(config => { const token = localStorage.getItem('authToken'); if (token) { config.headers.Authorization = `Bearer ${token}`; } return config; }); - 前端路由守卫
用react-router-dom v6自定义路由组件,校验用户角色是否有权限访问Admin页面:import { Navigate, Outlet } from 'react-router-dom'; const AdminRoute = () => { // 解码JWT获取用户角色 const getCurrentUser = () => { const token = localStorage.getItem('authToken'); if (!token) return null; // 解码JWT的payload部分 const payload = JSON.parse(atob(token.split('.')[1])); return payload; }; const user = getCurrentUser(); const isAdmin = user?.roles?.includes('ROLE_ADMIN'); // 有权限则渲染子路由,否则跳转到登录页 return isAdmin ? <Outlet /> : <Navigate to="/login" replace />; }; // 路由配置中使用 function AppRoutes() { return ( <Routes> <Route path="/login" element={<LoginPage />} /> <Route path="/admin" element={<AdminRoute />}> <Route index element={<AdminDashboard />} /> <Route path="users" element={<UserManagement />} /> {/* 其他Admin专属页面 */} </Route> <Route path="/" element={<PublicHome />} /> </Routes> ); } - 权限错误处理
设置响应拦截器,当后端返回403时,清除Token并跳转到登录页:axios.interceptors.response.use( response => response, error => { if (error.response?.status === 403) { localStorage.removeItem('authToken'); window.location.href = '/login'; } return Promise.reject(error); } );
内容的提问来源于stack exchange,提问作者Eva
相关产品推荐
相关产品推荐

