Firebase Auth+Vue Router路由守卫问题:未授权路径保护失效
问题解决思路与代码修改
1. 修复Store中AuthState的异步逻辑
onAuthStateChanged是订阅式API,直接用await无法等待认证状态回调执行。需要将其包装成Promise,确保认证状态初始化完成后再执行后续逻辑:
// STORE state: () => ({ isAuthReady: false, // 初始设为false,明确未就绪状态 user: null, userInfo: [] // 对应原代码中的用户信息存储字段 }), mutations: { setAuthReady(state, value) { state.isAuthReady = value }, setUser(state, user) { state.user = user }, setUserInfo(state, info) { state.userInfo = info } }, actions: { AuthState({ dispatch }) { // 包装为Promise,等待首次认证状态回调触发 return new Promise((resolve) => { const unsubscribe = auth.onAuthStateChanged(async (userFirebase) => { await dispatch("LoginStatus", userFirebase); unsubscribe(); // 仅需一次初始化,取消订阅 resolve(); }); }); }, async LoginStatus({ commit, dispatch }, user) { if (user) { commit("setUser", user); // 等待用户信息、管理员状态加载完成 await dispatch("UserProfile", user); await dispatch("isAdmin"); commit("setAuthReady", true); // 所有认证操作完成后标记就绪 } else { commit("setUser", null); commit("setUserInfo", []); commit("setAuthReady", true); // 未登录也标记就绪,避免无限等待 } }, // 示例:异步获取用户信息的方法 async UserProfile({ commit }, user) { const profile = await auth.getUser(user.uid); commit("setUserInfo", profile); }, async isAdmin({ commit }) { // 管理员权限判断逻辑 } }
2. 修改路由守卫,等待认证状态就绪
在路由守卫中先等待AuthState执行完成,确保状态初始化后再做权限判断:
// ROUTER router.beforeEach(async (to, from, next) => { // 若认证状态未就绪,先等待初始化完成 if (!store.state.auth.isAuthReady) { await store.dispatch("auth/AuthState"); } if (to.meta.requiresAuth) { // 基于初始化后的状态判断权限 if (store.state.auth.user && store.state.auth.userInfo.length) { next(); } else { await store.dispatch("auth/openLoginForm"); next("/"); } } else { next(); } });
3. 解决页面刷新/清缓存后的状态重置问题
Vuex状态存于内存,刷新后会丢失,可通过两种方式处理:
- 依赖Firebase的
onAuthStateChanged:页面刷新时App.vue的created钩子调用AuthState,会自动拉取Firebase的登录状态 - 可选:将用户关键信息持久化到本地存储,在Store初始化时读取:
// STORE的state初始化时读取localStorage state: () => ({ isAuthReady: false, user: JSON.parse(localStorage.getItem("authUser")) || null, userInfo: JSON.parse(localStorage.getItem("authUserInfo")) || [] }), // 在mutations中同步更新本地存储 mutations: { setUser(state, user) { state.user = user; localStorage.setItem("authUser", JSON.stringify(user)); }, setUserInfo(state, info) { state.userInfo = info; localStorage.setItem("authUserInfo", JSON.stringify(info)); } }
关键注意点
- 确保
App.vue的created钩子中调用AuthState,保证页面加载时优先初始化认证状态:// App.vue created() { this.$store.dispatch("auth/AuthState"); }
内容的提问来源于stack exchange,提问作者SPcz
相关产品推荐
相关产品推荐

