Nuxt Auth问题:AccessToken过期跳转登录而非自动刷新
问题描述
- 已集成
@nuxtjs/auth-next@5.0.0-1648802546.c9880dc模块,采用AccessToken(有效期30分钟)+RefreshToken(有效期8小时)的令牌机制 - 期望实现:每30分钟自动通过RefreshToken刷新AccessToken;8小时后RefreshToken过期时自动登出
- 当前问题:AccessToken过期后直接跳转至登录页,仅用户主动操作时才会触发token更新,用户闲置时会触发登录跳转
当前配置
nuxt.config.js
auth: { redirect: { login: "/", logout: "/", callback: "/dashboard", home: "/dashboard", }, strategies: { local: { scheme: "refresh", token: { property: "tokens.access.token", global: true, type: "Bearer", maxAge: 60 * 30, // 30分钟 }, refreshToken: { property: "tokens.refresh.token", data: "refreshToken", maxAge: 60 * 60 * 8 // 8小时 }, user: { property: "user", autoFetch: false, }, endpoints: { login: { url: "/users/login", method: "post" }, refresh: { url: "/users/refresh-tokens", method: "post" }, user: false, logout: "", }, autoLogout: true, tokenRequired: true, tokenType: 'JWT', }, }, plugins: [{ src: "~/plugins/axios.js", ssr: true }], }
/plugins/axios.js
export default function ({ store, app: { $axios }, route, redirect }) { // 请求拦截:为非登录请求添加Bearer令牌 $axios.onRequest((config) => { let accessToken = store.state.token; if (accessToken && config.url !== "/users/login") { config.headers.Authorization = "Bearer " + accessToken; } return config; }); // 错误拦截:令牌无效或过期时跳转登录页 $axios.onError(async (error) => { const statusCode = error.response ? error.response.status : -1; if (route.path !== "/" && statusCode === 401) { return redirect("/"); } // return Promise.reject(error); }); }
解决方案
1. 完善Auth模块自动刷新配置
refresh scheme原生支持自动刷新,需补充关键配置确保生效:
在local策略中添加以下参数:
autoRefresh: true, // 显式开启自动刷新(默认已开启,可明确声明) refreshInterval: 60 * 29 * 1000 // 提前1分钟触发刷新,单位毫秒
确保token.maxAge和refreshToken.maxAge与后端返回的令牌有效期完全一致,避免时间差导致的异常。
2. 修复Axios拦截器的401处理逻辑
当前拦截器直接跳转登录会打断Auth模块的自动刷新流程,需修改为仅在RefreshToken失效时才跳转:
$axios.onError(async (error) => { const statusCode = error.response ? error.response.status : -1; if (statusCode === 401) { // 检查RefreshToken是否已过期 const isRefreshTokenExpired = store.state.auth.strategy.refreshTokenExpired(); if (isRefreshTokenExpired && route.path !== "/") { await store.dispatch('auth/logout'); return redirect("/"); } // 未过期则交给Auth模块自动刷新并重试请求 return Promise.reject(error); } return Promise.reject(error); });
3. 添加客户端定时刷新任务(解决闲置时不刷新问题)
创建~/plugins/auth-refresh.js,在客户端定时触发token刷新:
export default function ({ store }) { if (!store.state.auth.loggedIn) return; // 计算提前1分钟刷新的间隔时间 const tokenExpiresIn = store.state.auth.token.expiresIn; const refreshInterval = (tokenExpiresIn - 60) * 1000; const refreshTimer = setInterval(async () => { if (store.state.auth.loggedIn) { try { await store.dispatch('auth/refreshTokens'); } catch (e) { // 刷新失败则清除定时器并登出 clearInterval(refreshTimer); await store.dispatch('auth/logout'); } } else { clearInterval(refreshTimer); } }, refreshInterval); // 页面卸载时清除定时器 if (process.client) { window.addEventListener('beforeunload', () => { clearInterval(refreshTimer); }); } }
在nuxt.config.js的plugins数组中添加该插件(仅客户端运行):
plugins: [ { src: "~/plugins/axios.js", ssr: true }, { src: "~/plugins/auth-refresh.js", ssr: false } ]
4. 修正令牌获取方式
不要直接从store.state.token取令牌,改用Auth模块统一维护的状态:
修改Axios请求拦截器:
$axios.onRequest((config) => { const { token } = store.state.auth; if (token && config.url !== "/users/login" && config.url !== "/users/refresh-tokens") { config.headers.Authorization = `${token.type} ${token.value}`; } return config; });
内容的提问来源于stack exchange,提问作者Abdul Hadi P C
相关产品推荐
相关产品推荐

