vue.js - 如何使用 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
- 动作:尝试是从 main.js 调用的动作
- MUTATION:SET_TOKEN 是动作中首先调用的突变
- AXIOS:CALL 是 axios 对 api 的调用
- SIGN-IN:是从登录路由调用 getter
- AXIOS: RESPONSE 是 axios 的响应
- MUTATION: SET_USER 是 axios 请求完成后调用的突变
- AXIOS: SET_USER 是在 axios 响应后设置用户的时候。
解决方案
我不得不等到调度完成。更新了 main.js 文件:
store.dispatch('auth/attempt', localStorage.getItem('token')).then(() => {
new Vue({
router,
store,
render: h => h(App)
}).$mount('#app')
}
)
推荐阅读
- javascript - 当用户导航到其他页面并返回时不清除表单数据
- google-client - 使用 Google Drive Remote 进行数据版本控制:“googleapiclient.errors.UnknownApiNameOrVersion: name: drive version: v2”
- r - 计算经纬度坐标与移动动物之间的角度
- node.js - 尝试使用 mongoose 连接 mongodb 数据库时出现 MongooseServerSelectionError
- python - 触发 Fargate 处理上传到 S3 的文件
- reactjs - React & Webpack & Docker:在运行时将环境注入到 docker-container
- angular - 从另一个组件刷新组件
- reactjs - 测试:react-native (expo) 对 react-navigation 中的 Screen 组件进行快照
- mysql - 使用机密将用户添加到 MySQL 的 Kubernetes 部署
- windows - 我们可以使用 CNG(Windows Cryptography API)生成 BCrypt / SCrypt / Argon2 哈希密码吗?