You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.10.02 10:36:01