Nuxt auth-next调用logout()报window is not defined错误排查
问题原因
nuxtServerInit是Nuxt框架仅在Node.js服务端执行的生命周期钩子,运行环境中不存在浏览器专属的window全局对象。@nuxtjs/auth-next模块的logout方法内置了大量客户端专属逻辑:包括操作window.localStorage/window.document清除存储的凭证、触发前端路由重定向、调用OAuth协议依赖浏览器跳转的登出端点,这些逻辑在服务端执行时就会直接抛出window is not defined错误。- 你的代码还存在策略名不匹配问题:auth配置中实际定义的鉴权策略名为
azureAD,但代码中调用logout、读取token时传入的策略名是social,该问题也会导致鉴权逻辑执行异常。
可行解决方案
不要在服务端运行的nuxtServerInit中直接调用依赖浏览器环境的logout方法,根据执行环境拆分登出逻辑即可,以下是两种可落地的实现方式:
- 方案1:拆分服务端/客户端初始化逻辑
- 在
nuxtServerInit中仅做服务端可执行的状态操作:token有效则写入vuex,token无效则调用auth模块提供的服务端兼容的reset()方法重置状态,通过服务端响应对象直接重定向到登录页,不要调用logout。 - 新增客户端专属的
nuxtClientInit钩子,在客户端环境初始化时检查登录状态,未登录则调用logout执行客户端侧的清理逻辑。
参考实现代码:
你需要新增一个客户端插件来支持// store/index.js export const actions = { async nuxtServerInit({ commit }, { app, res }) { // 修正策略名为配置中实际存在的azureAD if (app.$auth.loggedIn) { const token = app.$auth.strategies.azureAD.token.get() // 此处替换为你实际的token有效性校验逻辑(过期时间、签名校验等) const isTokenValid = true if (isTokenValid) { commit('SET_TOKEN', token) } else { // 服务端仅重置auth模块内部状态,不调用依赖window的logout await app.$auth.reset() // 服务端直接返回302重定向到登录页 res.writeHead(302, { Location: '/' }) res.end() } } }, // 客户端专属初始化逻辑 async nuxtClientInit({ app }) { if (!app.$auth.loggedIn) { await app.$auth.logout('azureAD') } } }nuxtClientInit钩子,在nuxt.config.js的plugins数组中添加如下配置:
对应插件文件内容:{ src: '~/plugins/nuxt-client-init.js', mode: 'client' }// plugins/nuxt-client-init.js export default async (context) => { await context.store.dispatch('nuxtClientInit', context) } - 在
- 方案2:将校验逻辑迁移到全局路由中间件
路由中间件会同时在服务端首屏渲染、客户端路由跳转时触发,可通过process.client变量判断当前运行环境,仅在客户端环境调用logout方法,服务端直接做状态重置和重定向,示例代码:
最后将该中间件添加到nuxt.config.js的// middleware/auth-validate.js export default async function ({ app, redirect }) { if (app.$auth.loggedIn) { const token = app.$auth.strategies.azureAD.token.get() // 替换为实际的token有效性校验逻辑 const isTokenValid = true if (isTokenValid) { app.store.commit('SET_TOKEN', token) return } } // 未登录或token无效时按环境执行对应逻辑 if (process.client) { await app.$auth.logout('azureAD') } else { await app.$auth.reset() return redirect('/') } }router.middleware数组中即可生效。
内容的提问来源于stack exchange,提问作者Sathya Molagoda
相关产品推荐
相关产品推荐

