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

基于Laravel Passport的SPA如何在API调用时刷新laravel_token

解决Laravel Passport SPA自动刷新laravel_token的方案

嘿,这个问题我在开发Laravel+Vue SPA的时候也碰到过,刚好有一套实用的解决方案,咱们一步步来实现:

1. 后端配置调整

首先确保Passport的令牌过期时间和session配置合理,并且添加一个刷新令牌的接口:

1.1 设置令牌过期时间

在app/Providers/AuthServiceProvider.php的boot方法里,配置access token的过期时间,同时保证session有效期比token长:

public function boot()
{
    $this->registerPolicies();
    Passport::routes();
    
    // 设置access token有效期为1小时,session建议配置为2小时以上
    Passport::tokensExpireIn(now()->addHour());
}

1.2 创建刷新令牌接口

在routes/api.php中添加一个使用web中间件的接口,利用用户的有效session生成新的laravel_token:

use Illuminate\Http\Request;

Route::get('/refresh-token', function (Request $request) {
    // 检查用户session是否有效
    if (!$request->user()) {
        return response()->json(['error' => 'Session expired'], 401);
    }

    // 生成新的API令牌并设置到cookie
    $newToken = $request->user()->createToken('SPA Access Token')->accessToken;
    
    return response()->json(['success' => true])
        ->cookie(
            'laravel_token',
            $newToken,
            config('session.lifetime') * 60, // 和session有效期保持一致
            config('session.path'),
            config('session.domain'),
            config('session.secure'),
            true // 开启HttpOnly,提升安全性
        );
})->middleware('web');

2. 前端Axios拦截器实现

通过Vue的Axios拦截器,自动处理token过期的情况:

2.1 基础响应拦截器(捕获401后刷新)

在Vue入口文件(比如resources/js/app.js或main.js)中配置Axios:

import axios from 'axios';
import Vue from 'vue';

// 创建Axios实例,确保携带cookie
const api = axios.create({
    baseURL: '/api',
    withCredentials: true
});

// 响应拦截器:处理401错误并刷新token
api.interceptors.response.use(
    response => response,
    async (error) => {
        const originalRequest = error.config;
        
        // 仅处理首次401错误,避免无限循环
        if (error.response.status === 401 && !originalRequest._retry) {
            originalRequest._retry = true;
            
            try {
                // 调用刷新token接口
                await api.get('/refresh-token');
                // 重试原请求
                return api(originalRequest);
            } catch (refreshError) {
                // 刷新失败,跳转登录页
                window.location.href = '/login';
                return Promise.reject(refreshError);
            }
        }
        
        return Promise.reject(error);
    }
);

// 挂载到Vue原型,全局可用
Vue.prototype.$api = api;

2.2 可选:请求前提前刷新token

如果想避免出现401错误,可以在请求前检查token的过期时间,提前刷新:

import jwtDecode from 'jwt-decode';

// 请求拦截器:提前检查token有效期
api.interceptors.request.use(async (config) => {
    // 从cookie中获取laravel_token
    const getCookie = (name) => {
        const value = `; ${document.cookie}`;
        const parts = value.split(`; ${name}=`);
        return parts.length === 2 ? parts.pop().split(';').shift() : null;
    };
    
    const token = getCookie('laravel_token');
    if (token) {
        const decoded = jwtDecode(token);
        const now = Date.now() / 1000;
        
        // 如果token在5分钟内过期,提前刷新
        if (decoded.exp - now < 300) {
            try {
                await api.get('/refresh-token');
            } catch (e) {
                window.location.href = '/login';
            }
        }
    }
    
    return config;
});

3. 关键注意事项

  • 确保config/session.php中的lifetime配置比token过期时间长,这样token过期时session仍有效,才能刷新token。
  • 必须开启Axios的withCredentials: true,否则请求不会携带cookie。
  • 生产环境建议开启session.secure,确保cookie仅通过HTTPS传输。

这样配置后,用户在长时间不刷新页面的情况下,token过期时会自动刷新,无需手动操作,大幅提升SPA的用户体验。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.20 10:35:03