首页 > 解决方案 > 如何使用 Vuex 异步操作和变异进行身份验证?

问题描述

我正在使用 Vuex 和 Axios 进行身份验证。我想在使用 localStorage 刷新浏览器时保持登录状态(是的,我知道这不是最安全的解决方案)。为了从 api 获取用户,我在 vuex auth 文件中使用了一个异步操作。

如果用户没有登录,他只能看到登录页面(SPA)。要查看用户是否已登录,我使用了 router.beforeEach()=>{if(!store.getters['auth/authenticated'])...}. 每次刷新 axios 请求都会发送,但登录页面不会等待响应显示。我看了一个 youtube 教程,我可以看到,我做的一切都是一样的。您可以在下面看到控制台日志。

如何设置路由器等待 axios 响应和 SET_USER 突变?

这是我想查看用户是否登录的 Vue 主文件:

store.dispatch('auth/attempt', localStorage.getItem('token')).then(

   new Vue({
     router,
     store,
     render: h => h(App)
   }).$mount('#app')
)

vuex auth 模块中的尝试操作:

async attempt({ commit }, token) {
            console.log('ACTION ATTEMPT: SET_TOKEN', token)
            commit('SET_TOKEN', token)

            try {
                console.log('AXIOS CALL: to auth/me')
                let response = await axios.get('auth/me');

                console.log('AXIOS RESPONSE: response.data', response.data)
                commit('SET_USER', response.data)

                console.log('AXIOS: SET_USER', response.data)
            } catch (error) {
                console.log('error')
                commit('SET_TOKEN', null)
                commit('SET_USER', null)
            }
        }

突变:

mutations: {
        SET_TOKEN(state, token) {
            state.token = token
            console.log('MUTATION: SET_TOKEN in mutation', state.token)
        },

        SET_USER(state, user) {
            state.user = user
            console.log('MUTATION: SET_USER in mutation', state.user)
        }
    },

启用标头和本地存储的订阅者文件:

store.subscribe((mutation) => {
    switch (mutation.type) {
        case 'auth/SET_TOKEN':
            if (mutation.payload) {
                axios.defaults.headers.common['Authorization'] = `Bearer ${mutation.payload}`
                localStorage.setItem('token', mutation.payload)
            } else {
                axios.defaults.headers.common['Authorization'] = null
                localStorage.removeItem('token') 
            }
            break;
    }
})

吸气剂:

getters: {
        authenticated(state) {
            console.log('SIGN-IN: authenticated token', state.token)
            console.log('SIGN-IN: authenticated user', state.user)
            return state.token && state.user
        },

        user(state) {
            return state.user
        }
    },

Vue 路由器:

Vue.use(VueRouter)

const routes = [
  { path: "*", component: PageNotFound },
  {
    path: '/',
    name: 'home',
    component: Home,
    meta: {
      requiresAuth: true,
    },
  },
  {
    path: '/signin',
    name: 'signin',
    component: signin,
   beforeEnter: (to, from, next) => {
      console.log('try to signin', store.getters['auth/authenticated']);
      if (!store.getters['auth/authenticated']) {
        return next()
      }
      else return next('');
    }
  },
]

const router = new VueRouter({
  mode: 'history',
  base: process.env.BASE_URL,
  routes
})

router.beforeEach((to, from, next) => {
  // console.log('store.authenticated',store.getters['auth/authenticated'])
  if (to.meta.requiresAuth && !store.getters['auth/authenticated']) {
    next('signin');
  }
  else next();
  // next();
})

export default router

和带有日志的控制台: 在此处输入图像描述

  1. 动作:尝试是从 main.js 调用的动作
  2. MUTATION:SET_TOKEN 是动作中首先调用的突变
  3. AXIOS:CALL 是 axios 对 api 的调用
  4. SIGN-IN:是从登录路由调用 getter
  5. AXIOS: RESPONSE 是 axios 的响应
  6. MUTATION: SET_USER 是 axios 请求完成后调用的突变
  7. AXIOS: SET_USER 是在 axios 响应后设置用户的时候。

标签: vue.jsauthenticationasynchronousaxiosvuex

解决方案


我不得不等到调度完成。更新了 main.js 文件:

store.dispatch('auth/attempt', localStorage.getItem('token')).then(() => {
  new Vue({
    router,
    store,
    render: h => h(App)
  }).$mount('#app')
}
)

推荐阅读