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

如何让Axios自动传递Cookie与授权令牌?Laravel Sanctum+Vue.js问题

解决Laravel Sanctum + Vue Axios页面刷新后需重新登录的问题

核心问题分析

你当前在登录时动态添加Axios请求拦截器携带Bearer令牌,但页面刷新后拦截器配置会丢失,且未持久化存储令牌;另外如果是SPA场景,Sanctum推荐使用Cookie会话认证,无需手动处理Bearer令牌。以下分两种场景给出解决方案:


方案一:使用Sanctum SPA Cookie认证(推荐)

这种方式依赖Cookie自动传递会话信息,无需手动管理令牌,更符合SPA场景的最佳实践。

1. 服务端补充配置

打开config/sanctum.php,确保stateful数组包含你的前端域名(比如前端运行在localhost:8080):

'stateful' => explode(',', env('SANCTUM_STATEFUL_DOMAINS', sprintf(
    '%s%s',
    'localhost,localhost:8080,127.0.0.1,127.0.0.1:8000,::1',
    env('APP_URL') ? ','.parse_url(env('APP_URL'), PHP_URL_HOST) : ''
))),

或者直接在.env文件中设置:

SANCTUM_STATEFUL_DOMAINS=localhost:8080,127.0.0.1:8080

同时确保登录路由使用web中间件(因为Sanctum会话依赖web会话机制),比如在routes/api.php中:

use Illuminate\Http\Request;
use Illuminate\Support\Facades\Auth;

Route::post('/authenticate', function(Request $request) {
    $credentials = $request->only('email', 'password');
    if (!Auth::attempt($credentials)) {
        return response()->json(['message' => 'Invalid credentials'], 401);
    }
    return response()->json(['user' => Auth::user()]);
})->middleware('web');

2. 前端代码调整

修改Vuex Store的signIn action

移除手动设置Axios拦截器的代码,登录后直接通过Cookie会话获取用户信息:

async signIn({commit}, payload) {
    try{
        await axios.get('/sanctum/csrf-cookie');
        await axios.post('/api/authenticate', payload);
        // 登录成功后直接拉取用户信息,Cookie会自动携带
        return store.dispatch('getUser');
    } catch(e) {
        throw 'User can not be authenticated';
    }
}

确保Axios全局配置正确

你的app.js中已经设置了axios.defaults.withCredentials = true,这个配置必须保留,它会让Axios自动携带Cookie。


方案二:使用API Bearer令牌(适合非SPA场景)

如果需要使用Bearer令牌,需将令牌持久化存储,页面刷新后自动读取并配置Axios。

1. 前端代码调整

在app.js初始化时读取本地存储的令牌

import './bootstrap';
import { createApp } from 'vue';
import router from './routes';
import axios from 'axios';
import store from './store/index.js'

axios.defaults.withCredentials = true;
axios.defaults.baseURL = 'http://127.0.0.1:8000/';

// 页面刷新时读取本地存储的令牌,自动配置Authorization头
const authToken = localStorage.getItem('auth_token');
if (authToken) {
    axios.defaults.headers.common['Authorization'] = `Bearer ${authToken}`;
}

import App from './components/App.vue';

store.dispatch('getUser').then(() => {
    const app = createApp(App);
    app.use(router);
    app.use(store);
    app.mount('#app');
});

修改Vuex Store的signIn action

登录成功后将令牌存入本地存储,并配置Axios默认头:

async signIn({commit}, payload) {
    try{
        await axios.get('/sanctum/csrf-cookie');
        const res = await axios.post('/api/authenticate', payload);
        
        if(res.data.status_code == 200) {
            // 将令牌存入本地存储
            localStorage.setItem('auth_token', res.data.access_token);
            // 配置Axios全局Authorization头
            axios.defaults.headers.common['Authorization'] = `Bearer ${res.data.access_token}`;
            return store.dispatch('getUser');
        } else {
            throw res.message;
        }
    } catch(e) {
        throw 'User can not be authenticated';
    }
}

修改Vuex Store的logout action

登出时清除本地存储的令牌和Axios配置:

async logout({commit}) {
    await axios.post('/api/logout').then(res => {
        commit('setUser', null);
        commit('setAuthenticated', false);
        // 清除本地存储的令牌
        localStorage.removeItem('auth_token');
        // 移除Axios的Authorization头
        delete axios.defaults.headers.common['Authorization'];
    }).catch(() => {
        commit('setUser', null);
        commit('setAuthenticated', false);
        localStorage.removeItem('auth_token');
        delete axios.defaults.headers.common['Authorization'];
    })
}

通用注意事项

  • 确保config/cors.php中的allowed_origins包含你的前端域名,supports_credentials设为true
  • 如果前后端域名不同,需确保浏览器允许第三方Cookie(localhost环境下通常默认允许)

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.08 15:37:19