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

基于React+Laravel Sanctum实现Token过期自动登出方案咨询

Laravel Sanctum Token过期自动登出的实现位置与方案

你的项目用Laravel Sanctum生成1分钟过期的token,想要实现token过期时自动登出并跳转登录页,自动登出逻辑需要分两部分实现,分别放在RequireAuth.jsx和axios拦截器文件中,Login.jsx只负责登录时的状态存储,不适合放全局过期处理逻辑,具体方案如下:

一、先补充后端返回token过期时间

首先需要让后端把token的过期时间一起返回给前端,修改你的AuthController代码:

// AuthController 生成token并返回过期时间
$tokenResult = $user->createToken('remember_token', expiresAt:now()->addMinute());
$remember_token = $tokenResult->plainTextToken;
// 获取token过期时间
$expires_at = $tokenResult->accessToken->expires_at;

// 返回数据时带上expires_at
return response()->json([
    'remember_token' => $remember_token,
    'user' => $user,
    'roles_name' => $roles_name, // 保留你的原有逻辑
    'role_id' => $user->role_id,
    'expires_at' => $expires_at
]);

二、Login.jsx的修改(仅存储状态)

在登录成功时,把后端返回的expires_at存入auth状态,不需要在这里处理过期逻辑:

// Login.jsx 的onSubmit函数中
const { remember_token, user, roles_name, role_id, expires_at } = response.data;

// 把过期时间存入auth状态
setAuth({ user, remember_token, roles_name, role_id, expires_at });

三、RequireAuth.jsx:主动检测token过期(路由守卫)

RequireAuth.jsx是路由守卫组件,每次路由切换或定时检查token是否即将过期,主动触发登出,这是预防式的处理:

import { useEffect } from 'react';
import { useAuth } from '../hooks/useAuth'; // 你的useAuth状态管理钩子
import { useNavigate } from 'react-router-dom';

const RequireAuth = ({ children, requiredRole }) => {
  const { auth, setAuth } = useAuth();
  const navigate = useNavigate();

  useEffect(() => {
    const checkTokenExpiry = () => {
      if (!auth?.expires_at) return;

      const expiryTime = new Date(auth.expires_at).getTime();
      const currentTime = Date.now();
      const bufferTime = 5000; // 提前5秒触发登出,避免刚好过期时请求失败

      // 检查是否即将过期或已过期
      if (currentTime + bufferTime >= expiryTime) {
        // 执行登出:清空状态、移除本地存储(如果有)、跳转登录页
        setAuth({});
        localStorage.removeItem('auth'); // 如果你用localStorage存了auth状态
        navigate('/login', { replace: true });
      }
    };

    // 初始化时检查一次
    checkTokenExpiry();
    // 定时检查,每10秒检测一次
    const interval = setInterval(checkTokenExpiry, 10000);

    // 组件卸载时清除定时器,避免内存泄漏
    return () => clearInterval(interval);
  }, [auth, setAuth, navigate]);

  // 保留你原有的路由守卫逻辑,比如检查用户是否登录、角色是否匹配
  if (!auth?.user) {
    navigate('/login', { replace: true });
    return null;
  }

  if (requiredRole && auth.role_id !== requiredRole) {
    navigate('/unauthorized', { replace: true });
    return null;
  }

  return children;
};

export default RequireAuth;

四、axios拦截器:被动处理401错误(请求失败时)

创建一个axios实例文件(比如axiosInstance.js),拦截所有响应,当后端返回401(token已过期)时,执行登出逻辑:

import axios from 'axios';
import { useAuth } from '../hooks/useAuth';
import { useNavigate } from 'react-router-dom';
import { createContext, useContext } from 'react';

// 创建Auth上下文,解决axios拦截器无法直接使用React Hooks的问题
const AuthContext = createContext();

export const AuthProvider = ({ children }) => {
  const { auth, setAuth } = useAuth();
  const navigate = useNavigate();
  return <AuthContext.Provider value={{ auth, setAuth, navigate }}>{children}</AuthContext.Provider>;
};

// 创建axios实例
const axiosInstance = axios.create({
  baseURL: process.env.REACT_APP_API_URL, // 替换成你的API地址
});

// 请求拦截器:自动在请求头添加token
axiosInstance.interceptors.request.use(
  (config) => {
    const { auth } = useContext(AuthContext);
    if (auth?.remember_token) {
      config.headers.Authorization = `Bearer ${auth.remember_token}`;
    }
    return config;
  },
  (error) => Promise.reject(error)
);

// 响应拦截器:处理401错误
axiosInstance.interceptors.response.use(
  (response) => response,
  (error) => {
    const { setAuth, navigate } = useContext(AuthContext);
    // 当后端返回401(token过期或无效)时,执行登出
    if (error.response?.status === 401) {
      setAuth({});
      localStorage.removeItem('auth');
      navigate('/login', { replace: true });
    }
    return Promise.reject(error);
  }
);

export default axiosInstance;

为什么不放在Login.jsx?

Login.jsx只负责处理登录提交的一次性逻辑,用户登录后这个组件就会被卸载,无法持续检测token状态或拦截全局请求错误,所以不适合放自动登出逻辑。

内容的提问来源于stack exchange,提问作者Christian Medallada

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.03 09:19:58