Nuxt3+Laravel生产环境刷新页面用户自动登出问题排查
Nuxt 3 + Laravel Sanctum 生产环境页面刷新丢失登录状态排查方案
以下是针对你遇到的问题的具体排查方向和解决方案:
Cookie 域名与跨域配置错误
本地开发用localhost不会有跨域域名问题,但生产环境主站example.com和APIapi.example.com属于子域名,需确保Sanctum的Cookie配置正确:- 检查Laravel
.env文件:SANCTUM_STATEFUL_DOMAINS=example.com,api.example.com(包含主站和API域名,不要带协议)SESSION_DOMAIN=.example.com(前缀加.,让所有子域名共享Cookie)
- 打开浏览器开发者工具的Application面板,查看Cookie详情:
- 确认
laravel_session和XSRF-TOKEN的Domain为.example.com,Path为/ - 生产环境需开启
Secure属性(确保HTTPS下传输),同时HttpOnly属性需正确设置(laravel_session应为HttpOnly,XSRF-TOKEN不需要)
- 确认
- 检查Laravel
静态生成(SSG)模式下的状态恢复问题
你用npm run generate生成了静态文件,Nuxt运行在纯静态模式,没有服务器端上下文,刷新页面时只能依赖客户端恢复状态:- 检查认证状态的初始化逻辑:
- 确保在客户端(如
app.vue的onMounted钩子、Pinia/Vuex store的初始化方法)中,从Cookie读取token并验证用户身份 - 避免在服务器端生命周期(如
serverPrefetch)中处理认证逻辑,静态生成后这些代码不会执行
- 确保在客户端(如
- 验证Nuxt的客户端Cookie读取是否正常:
- 使用Nuxt的
useCookieAPI读取XSRF-TOKEN或自定义token,确认刷新页面后能正确获取到值
- 使用Nuxt的
- 检查认证状态的初始化逻辑:
Laravel Fallback路由拦截静态资源
当前的Laravel路由会匹配所有请求并返回index.html,可能导致Nuxt生成的静态资源(如_nuxt目录下的JS/CSS)无法正确加载,进而导致认证逻辑失效:- 调整Laravel路由优先级,优先匹配静态资源:
// 先处理Nuxt静态资源 Route::get('{asset}', function ($asset) { $path = public_path($asset); if (file_exists($path)) { return response()->file($path); } abort(404); })->where('asset', '(_nuxt|favicon\.ico|robots\.txt).*'); // 再处理SPA Fallback Route::get('{any}', [RedirectableLinkController::class, 'show'])->where('any', '.*'); - 刷新页面后查看Network面板,确认所有
_nuxt开头的资源返回200状态码
- 调整Laravel路由优先级,优先匹配静态资源:
API请求未正确携带Cookie
即使Cookie存在,若Nuxt的API请求未配置credentials: true,则不会携带Cookie到API服务器,导致认证失败:- 检查Nuxt配置文件
nuxt.config.ts:export default defineNuxtConfig({ nitro: { routeRules: { '/api/**': { proxy: 'https://api.example.com/**', credentials: true // 关键配置,确保携带Cookie } } } }) - 查看刷新后发起的第一个API请求(如获取用户信息的请求),确认Request Headers中包含
Cookie字段,且包含正确的laravel_session和XSRF-TOKEN
- 检查Nuxt配置文件
客户端状态初始化时机错误
若在Cookie未读取完成前就发起认证请求,会导致请求未携带有效认证信息:- 调整认证逻辑的执行时机:
- 在Pinia store中,先读取Cookie中的token,再调用
fetchUser接口 - 示例代码:
export const useAuthStore = defineStore('auth', { state: () => ({ user: null, token: useCookie('XSRF-TOKEN') }), actions: { async fetchUser() { if (!this.token) return try { const { data } = await useFetch('/api/user', { credentials: true }) this.user = data.value } catch (e) { this.user = null this.token = null } } }, mounted() { this.fetchUser() } })
- 在Pinia store中,先读取Cookie中的token,再调用
- 调整认证逻辑的执行时机:
内容的提问来源于stack exchange,提问作者rabie ali
相关产品推荐
相关产品推荐

