javascript - Vuejs 路由导航守卫异步身份验证状态请求

标签 javascript vue.js firebase-authentication vue-router vuex

我正在使用 firebase 在我的 vuejs 应用程序中进行身份验证。在我的根 (main.js) vue 组件中。

  created() {
    auth.onAuthStateChanged((user) => {
      this.$store.commit('user/SET_USER', user);
      if (user && user.emailVerified) {
        this.$store.dispatch('user/UPDATE_VERIFIED', {
          userId: user.uid,
        });
        // SUCCESSFUL LOGIN
        this.$router.replace('dashboard');
      } else if (user && !user.emailVerified) {
        this.$router.replace('verify');
      }
    });

所以基本上,我的路由器导航守卫正在检查身份验证状态并在每条路线之前进行路由。

router.beforeEach((to, from, next) => {
  const currentUser = firebaseApp.auth().currentUser;
  const requiresAuth = to.matched.some(record => record.meta.requiresAuth);
  const allowUnverified = to.matched.some(record => record.meta.allowUnverified);

  if (requiresAuth && !currentUser) {
    next('login');
  } else if (currentUser
              && !currentUser.emailVerified
              && !allowUnverified
              && to.path !== '/verify') {
    next('verify');
  } else if (!requiresAuth && currentUser) {
    next('dashboard');
  } else {
    next();
  }
});

发生的事情是,当您刷新页面(使用有效的身份验证 token )时,您点击了路由守卫的分支 1,stateChanges 并且调用处理程序以重定向到/dashboard。登录时如此清爽,始终将您带到仪表板路线,而不是您所在的当前路线。

我该如何处理这种情况?向每个身份验证组件添加一个 beforeEnter 守卫对我来说很难闻 Data Fetching Vue Docs .

这应该在商店中而不是在根实例上创建的钩子(Hook)吗?任何帮助是极大的赞赏。这种模式让我很困惑。

最佳答案

快速修复

如果用户存在并且不需要身份验证,为什么要将他重定向到另一个页面(仪表板)?

  } else if (!requiresAuth && currentUser) {
    next('dashboard');
  } else {
    next();
  }

你可以让路由继续。

  if (requiresAuth && !currentUser) {
    next('login');
  } else if (requiresAuth && !currentUser.emailVerified && !allowUnverified) {
    next('verify');
  } else {
    next();
  }

您还需要从 onAuthStateChanged 回调中删除 this.$router.replace('dashboard');。请参阅下文以获得更深入的答案。

深度

我会避免在 Vue 组件中放置身份验证路由 逻辑。虽然有一天它可能有意义,但在这种情况下,它可以完全避免。

我喜欢将 Vuex 存储实例放在一个独立的模块中,这样我就可以在别处使用它,而不仅限于 Vue。

import Vue from 'vue';
import Vuex from 'vuex';
// Configuration is generated with a function, so testing the store is easier
import getConfig from './config';

Vue.use(Vuex);

export default new Vuex.Store(getConfig());

因此可以将身份验证逻辑移至 auth.js 服务。

import store from './store';
import router from './router';

// other auth related code, you can even export a common API
// to use within your app.
// like this simple wrapper, which hides the fact that you're using firebase
export function getUser() {
  return firebaseApp.auth().currentUser;
}
export default { getUser }

auth.onAuthStateChanged((user) => {
  // store/business logic should be inside the store.
  store.dispatch('user/AUTH_STATE_CHANGED', user);
  // minimal handling of mandatory steps in the login or sign up process
  if (!user) {
     router.push('login');
  } else if (user && !user.emailVerified) {
    router.push('verify');
  }
});

如果用户正确登录,则没有理由重定向到这里。由于全局导航守卫将完成大部分重定向工作,您可以只 redirect to the current route with router.go() or router.push(router.currentRoute) .

其实这个navigation guard可以在上面提到的auth.js服务里面注册。

router.beforeEach((to, from, next) => {
  const currentUser = getUser();
  const requiresAuth = to.matched.some(record => record.meta.requiresAuth);
  const allowUnverified = to.matched.some(record => record.meta.allowUnverified);

  if (requiresAuth && !currentUser) {
    next('login');
  } else if (requiresAuth && !currentUser.emailVerified && !allowUnverified) {
    next('verify');
  } else {
    next();
  }
});

然后,将简单的导航守卫添加到登录后不应到达的路线。

path: '/login',
beforeEnter: (to, from, next) => {
    if (auth.getUser()) {
        next('dashboard');
    } else {
        next();
    }
},

要点是:仅在导航到受限页面时强制重定向。

当登录用户刷新页面时,没有理由重定向到/dashboard。如果同一用户尝试导航到登录,则有理由重定向到 /dashboard

关于javascript - Vuejs 路由导航守卫异步身份验证状态请求,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/49621891/

相关文章:

返回键的javascript排序函数

laravel - VueJS、Axios、Laravel - 捕获错误

javascript - Vue默认选择对象上的选项

java - 如何在 Android 中使用 Firebase 从当前用户获取特定数据?

database - auth !== null 有多安全?火力地堡

javascript - 如何在需要函数的事件中传递参数?

javascript - 使用两个关联在 Sequelize 中获取模型的实例

javascript - 在 React Native 应用程序中获取请求后,MobX 存储未更新

javascript - axios get 中出现未定义错误

iOS/Swift/Firebase 身份验证 : Help Needed on Accessing "isNewUser"