Laravel Sanctum+React SPA登出后仍可访问受保护路由问题求助
我用Laravel Sanctum和React开发简单SPA时遇到了棘手问题:执行任意前端操作时laravel_session和XSRF-TOKEN Cookie会自动更新,导致/logout路由失效——就算控制台提示“CSRF token mismatch.”,还是能访问后端受保护路由。
问题重现流程
- 无Cookie状态下调用
/login授权成功,可访问受保护路由(忽略/dashboard调用,已在cors.php中拦截,仅用于跳转); - 成功调用
/api/cars获取车辆数据; - 调用
/logout使当前Token失效,预期后续无法访问/api/cars; - 但实际后续仍能正常访问
/api/cars,即便Token已失效。
核心异常:每次前端操作都会自动更新laravel_session和XSRF-TOKEN Cookie,但控制台看不到登出后有调用/login的记录。我怀疑是组件渲染的问题,但找不到具体位置,附上所有React组件代码,求技术帮助!
可能的排查方向与解决方案
1. 检查Sanctum登出逻辑是否正确
确保Laravel后端的/logout路由彻底销毁会话:
// 根据路由配置选择api.php或web.php Route::post('/logout', function (Illuminate\Http\Request $request) { Auth::guard('web')->logout(); $request->session()->invalidate(); $request->session()->regenerateToken(); return response()->json(['message' => 'Logged out successfully']); })->middleware('auth:sanctum');
登出时必须同时执行销毁守卫、失效会话、重新生成CSRF Token三个操作,避免旧会话残留导致授权状态未清除。
2. 前端登出后强制清除Cookie并重置请求实例
React端登出后,需手动清除相关Cookie,并重置请求库的默认配置:
import axios from 'axios'; import Cookies from 'js-cookie'; import { useNavigate } from 'react-router-dom'; const handleLogout = async () => { try { await axios.post('/logout'); // 清除Sanctum相关Cookie Cookies.remove('laravel_session'); Cookies.remove('XSRF-TOKEN'); // 重置Axios默认Headers axios.defaults.headers.common['X-XSRF-TOKEN'] = ''; // 跳转至登录页 navigate('/login'); } catch (error) { console.error('Logout failed:', error); } };
如果不主动清除Cookie,浏览器会自动携带旧会话Cookie,导致Sanctum仍识别为已授权状态。
3. 排查请求拦截器的自动重试逻辑
检查Axios拦截器是否存在自动重试或重新获取Token的逻辑,这会导致登出后Cookie被重新激活:
// 错误示例:拦截器自动重试触发Cookie更新 axios.interceptors.response.use( response => response, async error => { if (error.response.status === 419) { // 自动获取CSRF Token会更新Cookie,重建会话 await axios.get('/sanctum/csrf-cookie'); // 重试请求会携带新Cookie,导致授权状态恢复 return axios(error.config); } return Promise.reject(error); } );
需在拦截器中添加用户状态判断,登出后禁用这类自动重试逻辑,避免Cookie被意外更新。
4. 检查组件挂载时的自动请求
排查全局Layout、路由守卫等组件,是否在未判断登录状态的情况下自动发起授权相关请求:
// 错误示例:组件挂载时无条件获取CSRF Token import { useEffect } from 'react'; import axios from 'axios'; const Layout = ({ children }) => { useEffect(() => { // 未判断登录状态,登出后仍会更新Cookie axios.get('/sanctum/csrf-cookie'); }, []); return <div>{children}</div>; };
需添加用户状态判断,仅在未登录时调用/sanctum/csrf-cookie接口。
5. 验证Sanctum与CORS配置
检查Laravel配置文件:
config/sanctum.php的stateful数组需包含SPA域名;config/cors.php的supports_credentials需设为true;- 环境变量
SESSION_DOMAIN需与SPA域名一致(例如.yourdomain.com)。
内容的提问来源于stack exchange,提问作者YahorLukyanchyk
相关产品推荐
相关产品推荐

