React配合Sanctum如何实现未登录访客访问需权限组件时跳转登录页
解决方案
你现有逻辑的核心问题是getUser方法未处理请求异常场景:未登录时请求api/user返回401会抛出未捕获的错误,没有对应逻辑设置未登录状态,同时缺少加载状态判断,用户信息还没拉取完成就会触发误跳转。可按照以下步骤改造:
1. 补充状态字段与请求异常处理
首先在全局用户状态中新增三个配套字段:
isLogin:布尔值,明确标记当前用户是否登录authLoading:布尔值,标记是否正在拉取用户登录状态,避免加载阶段误判- 新增
clearUser、setLoginStatus、setAuthLoading三个action用于状态更新
首先给axios增加全局响应拦截器,统一处理401未登录逻辑:
// axiosConfig.js 补充响应拦截器 axiosConfig.interceptors.response.use( response => response, error => { if (error.response?.status === 401) { // 统一处理未登录:清空用户状态,跳转登录页 dispatch(actions.clearUser()) window.location.href = '/login' } return Promise.reject(error) } )
改造getUser逻辑,补充异常捕获和状态更新:
const fetchData = async () => { // Sanctum要求必须先请求csrf cookie,之前没加的话需要补上 await axiosConfig.get('/sanctum/csrf-cookie') const response = await axiosConfig.get('api/user'); return response.data; } export const getUser = () => async (dispatch) => { dispatch(actions.setAuthLoading(true)) try { const user = await fetchData() dispatch(actions.setUser(user)); dispatch(actions.setLoginStatus(true)) } catch (e) { // 401未登录会进入该分支 dispatch(actions.setLoginStatus(false)) dispatch(actions.clearUser()) } finally { dispatch(actions.setAuthLoading(false)) } }
2. 给路由配置增加权限标记
给你的所有路由新增meta字段,标记当前路由是否需要登录权限:
// 路由配置示例(React Router v6为例) const routes = [ { path: '/login', element: <Login />, meta: { requireAuth: false } // 公开路由,无需登录 }, { path: '/register', element: <Register />, meta: { requireAuth: false } }, { path: '/dashboard', element: <Dashboard />, meta: { requireAuth: true } // 需登录才可访问 }, // 其他路由按实际需求配置 ]
3. 统一在路由渲染层做权限判断
你提到所有路由都放在同一个组件内,直接在该组件的路由渲染逻辑中增加权限判断即可:
import { useRoutes, Navigate } from 'react-router-dom' import { useSelector } from 'react-redux' function App() { // 从全局状态取用户相关字段 const { authLoading, isLogin } = useSelector(state => state.user) // 等待用户状态拉取完成再渲染路由,避免出现登录页闪跳 if (authLoading) return <Loading /> return useRoutes(routes.map(route => { // 需登录的路由 + 用户未登录:替换为重定向逻辑 if (route.meta?.requireAuth && !isLogin) { return { ...route, element: <Navigate to="/login" replace /> } } return route })) }
补充说明:如果使用的是React Router v5版本,将代码中的
Navigate组件替换为Redirect组件即可,判断逻辑完全一致。全局401拦截器会兜底所有接口的未登录场景,比如登录状态过期后调用业务接口也会自动触发重定向,不需要每个组件单独处理。
内容的提问来源于stack exchange,提问作者Krystian432345
相关产品推荐
相关产品推荐

