这是参考了官网文档和网上一些文章之后自己对于登录这一块的理解
登录流程是 在客户端发送用户名密码到 服务端,服务端验证成功后返回token存储用户权限,前端用cookie存储在本地,在路由跳转(router.beforeEach)中判断是否存在token。
权限控制是在router.beforeEach中判断token中的权限和要去往(to)页面的路由信息(router meta)中配置的权限是否匹配。
页面
两个输入框,一个按钮。
把绑定数据,对用户输入的内容进行验证
src -> views ->login -> index.vue
按钮点击事件handleLogin()。对表单进行验证,验证通过,则将表单的内容传到store中的user/login,然后路由跳转至’/’
handleLogin() {
this.$refs.loginForm.validate(valid => {
if (valid) {
this.loading = true
// 请求store中的'user/login'方法,把表单的内容传过去
this.$store.dispatch('user/login', this.loginForm)
.then(() => {
this.$router.push({ path: this.redirect || '/', query: this.otherQuery })
this.loading = false
})
.catch(() => {
this.loading = false
})
} else {
console.log('error submit!!')
return false
}
})
},
src ->store -> modules -> user.js
前面提到的user/login就是在这个文件里面。
获取login index.vue传过来的用户名密码。SET_TOKEN方法将token存储在cookie中
// 用户登录
login({ commit }, userInfo) {
const { username, password } = userInfo
return new Promise((resolve, reject) => {
login({ username: username.trim(), password: password }).then(response => {
const { data } = response
// 设置token,作为用户已登录的前端标识,存在cookie中
commit('SET_TOKEN', data.token)
setToken(data.token)
resolve()
}).catch(error => {
reject(error)
})
})
},
src ->store -> modules -> user.js
获取用户信息。
这个方法会以上面保存的token为参数去请求用户的权限
// 获取用户信息
getInfo({ commit, state }) {
return new Promise((resolve, reject) => {
//请求获取权限
getInfo(state.token).then(response => {
const { data } = response
if (!data) {
reject('验证失败,请重新登录!')
}
const { roles, name, avatar, introduction } = data
// 角色roles必须是非空数组
if (!roles || roles.length <= 0) {
reject('getInfo: roles must be a non-null array!')
}
commit('SET_ROLES', roles)
commit('SET_NAME', name)
commit('SET_AVATAR', avatar)
commit('SET_INTRODUCTION', introduction)
resolve(data)
}).catch(error => {
reject(error)
})
})
},
分配权限
src -> router -> index.js路由表文件
路由表根据权限分为两类
constantRoutes 没有权限的限制,像登录界面、404、401等都在这里
asyncRoutes 异步路由,有权限的限制,管理界面都在这里
代码里通过在meta里面添加roles赋予权限
src -> permission.js文件里面
添加逻辑:获取用户信息,根据获取到的权限生成可访问的路由映射,然后通过addRouter方法动态添加路由
try
{
// 获取用户信息,角色必须是对象数组such as: ['admin'] or ,['developer','editor']
// await 等待异步完成,只能在async函数中使用
const { roles } = await store.dispatch('user/getInfo')
// 基于角色生成可访问的路由映射
const accessRoutes = await store.dispatch('permission/generateRoutes', roles)
// 动态添加可访问路由表
router.addRoutes(accessRoutes)
// hack方法,确保addRoutes已完成
// set the replace: true,所以导航不会留下历史记录
next({ ...to, replace: true })
}
catch (error)
{
// 删除token并转到登录页重新登录
await store.dispatch('user/resetToken')
Message.error(error || 'Has Error')
next(`/login?redirect=${to.path}`)
NProgress.done()
}
}
src -> store -> permission.js是对路由映射进行判断,加载符合权限的路由列表