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

Vue3+Pinia+Vue-Router路由守卫早于Pinia Store加载的问题

问题:基于Pinia Store实现路由守卫,禁止已登录用户访问登录/注册页

技术版本

vue@3.2.47
pinia@2.0.35
vue-router@4.1.6

当前认证逻辑实现

我使用Firebase做认证服务,通过Pinia Store管理认证状态,核心实现如下:

  • 新建了storeAuth.ts作为认证状态仓库,核心代码:
...

export const useStoreAuth = defineStore('storeAuth', () => {
  const user = ref(null)
  const loading = ref(false)
  const errorMessage = ref("")
  const successMessage = ref("")
  const router = useRouter()

  const init = () => {
    onAuthStateChanged(auth, (firebaseUser) => {  
      if (firebaseUser) {
        user.value = {}
        user.value.id = firebaseUser.uid
        user.value.email = firebaseUser.email
        console.log('logged in:',user);
      } else {
        user.value = null
        //console.log('logged out');
      }
    });
  }
...
const loginUser = (credentials) => {
    successMessage.value = ""
    errorMessage.value = ""
    loading.value = true

    signInWithEmailAndPassword(auth, credentials.email, credentials.password).then((userCredential) => {
      loading.value = false
      const firebaseUser = userCredential.user;
      router.push('/')
    }).catch((error) => {
      loading.value = false
      //console.log('Error while logging in:',error.message);
      switch (error.code) {
        case 'auth/user-not-found':
          errorMessage.value = "Email and/or password incorrect"
          break;

        case 'auth/wrong-password':
          errorMessage.value = "Email and/or password incorrect"
          break;

        case 'auth/too-many-requests':
          errorMessage.value = "Too many requests. Please reset your password"
          break;

        default:
          errorMessage.value = "There was an error during login"
          break;
      }
    });
  }
...
  • 登录流程通过调用loginUser函数传入账号凭证完成。

需求与遇到的问题

需要实现路由守卫规则:已登录用户禁止访问登录(signin)、注册(register)页面。

尝试直接在router/index.ts中获取Pinia Store的user值,但始终返回null。于是改用直接从Firebase获取用户的方案,代码如下,但该方案无效:

let currentUser = null

const getCurrentUser = async () => {
  return new Promise<void>((resolve) => {
    onAuthStateChanged(auth, (user) => {
      currentUser = user
      resolve()
    })
  })
}

const setupNavigationGuards = async () => {
  await getCurrentUser()

  router.beforeEach((to, from, next) => {
    currentUser = auth.currentUser

    if (currentUser && (to.name === 'signin' || to.name === 'register')) {
      next({ name: 'home' })
    } else {
      next()
    }
  })
}

// Call the setupNavigationGuards function
setupNavigationGuards()

我更希望基于Pinia Store中的user状态来实现路由守卫,因为后续需要扩展角色字段,实现管理员菜单控制,而不是直接依赖Firebase的用户对象。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.21 21:27:09