You need to enable JavaScript to run this app. Nuxt中间件如何正确访问Vuex Store实现用户编辑权限拦截
优惠活动
大模型
产品
解决方案
定价
更多

Nuxt中间件如何正确访问Vuex Store实现用户编辑权限拦截

报错根因定位
  • 报错Cannot read property 'uid' of null的核心诱因是执行时机不匹配,并非无法在中间件中访问Vuex Store:
    1. 项目的Vuex模块中currentUser初始值为null,这个值完全依赖异步的onAuthStateChangedAction回调(由认证SDK的状态监听触发)完成赋值,属于典型的异步流程。
    2. Nuxt中间件的执行时机远早于页面组件实例化:不管是首次页面加载还是客户端路由跳转,页级中间件都会在路由解析完成、页面组件渲染前执行完成。此时如果异步认证流程还未触发、没有提交SET_AUTH_USER变更Store,store.state.user.currentUser就会保持初始的null值,直接读取其uid属性自然抛出空引用错误——哪怕把重定向逻辑注释掉,只要存在直接读取currentUser.uid的代码行,就会触发报错。
    3. 同页面计算属性可以正常获取uid,是因为计算属性具备响应式特性:等异步认证流程完成、Store中的currentUser被更新后,计算属性会自动同步拿到最新值,和中间件执行阶段的空状态处于完全不同的时间节点,不存在逻辑矛盾。
可落地的修复方案

第一步:补充空值防御,消除基础报错

在中间件逻辑中不要直接对currentUser做链式属性读取,先对值做存在性判断,哪怕后续逻辑还有优化,也能先避免空引用崩溃:

middleware({ store, params, redirect }) {
  const currentUser = store.state.user.currentUser
  // 无登录用户时直接重定向,避免后续读取uid报错
  if (!currentUser) return redirect('/')
  // 路由参数uid与当前登录用户不匹配时重定向,拦截越权访问
  if (currentUser.uid !== params.uid) return redirect('/')
}

第二步:解决执行时机差,拿到准确的认证状态

仅做空值防御还不够——因为中间件执行时,认证状态大概率还没完成初始化,会把所有合法访问的用户也错误重定向走。需要调整逻辑,等认证状态初始化完成后再做越权校验:

  1. 先在Vuex的user模块中增加authReady状态,用来标记认证流程是否初始化完成:
    export const state = () => ({
      currentUser: null,
      authReady: false // 新增:标记认证初始化状态
    })
    
    export const mutations = {
      SET_AUTH_USER(state, payload) {
        state.currentUser = payload
      },
      // 新增:更新认证准备状态
      SET_AUTH_READY(state, value) {
        state.authReady = value
      }
    }
    
    export const actions = {
      async onAuthStateChangedAction({ commit, dispatch }, { authUser }) {
        try {
          if (authUser && authUser.emailVerified) {
            // 保留原有用户信息赋值逻辑
            const { uid, email, emailVerified, displayName /* 其余原有解构字段保持不变 */ } = authUser
            commit('SET_AUTH_USER', { uid, email, emailVerified, displayName })
            await dispatch('getUserProfile', authUser)
          } else {
            // 未登录/未验证时重置currentUser
            commit('SET_AUTH_USER', null)
          }
        } catch (error) {
          console.error('Error with Auth State observer: ', error)
        } finally {
          // 不管认证流程成功/失败,都标记初始化完成,释放路由等待
          commit('SET_AUTH_READY', true)
        }
      }
    }
    
  2. 将中间件改为异步形式,等待认证初始化完成后再做校验。Nuxt中间件本身支持返回Promise,只有当Promise resolve后,路由才会继续向下渲染:
    async middleware({ store, params, redirect }) {
      // 等待认证状态初始化完成
      while (!store.state.user.authReady) {
        // 小延迟轮询,避免阻塞事件循环
        await new Promise(resolve => setTimeout(resolve, 50))
      }
      const currentUser = store.state.user.currentUser
      // 未登录重定向
      if (!currentUser) return redirect('/')
      // 越权访问重定向
      if (currentUser.uid !== params.uid) return redirect('/')
    }
    

注意事项

  • 因为是客户端层面的拦截,不需要服务端渲染阶段执行校验,可以通过环境判断把这个中间件的运行范围限制为客户端,避免服务端执行时拿不到浏览器端的认证状态做无效判断。
  • 客户端路由拦截仅用于提升用户体验,不能作为最终的安全防线:用户可以通过手动修改前端状态绕过拦截,最终的越权校验必须在业务接口层做二次判断,才能从根源上禁止越权编辑的行为。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.11.07 13:45:04