1.用户权限控制
1.1 用户登录
1.1.1 流程分析
1) 用户登录界面,需要输入手机号密码
![](https://img-blog.csdnimg.cn/20210625223458743.png?x-oss-process=image/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3FxXzM4OTc3NTY2,size_16,color_FFFFFF,t_70)
2) 登录组件 login.vue
![](https://img-blog.csdnimg.cn/20210625223458694.png)
type="primary" :loading="loading" @click="submit('login-form')">{{ loading ? 'Loading...' : '登录' }} |
//提交登录表单 submit(ref) { //校验 this.$refs[ref].validate(valid => { if (!valid) return false; this.error = null; this.loading = true; //发送登录请求 this.$store.dispatch("createToken", this.model) .then(res => { if (res.state !== 1) { this.error = { title: "Error occurred", message: "Abnormal, please try again later!" }; } this.$router.replace({ path: this.$route.query.redirect ||"/" }); this.loading = false; }) .catch(err => { this.loading = false; }); }); } } |
- this.$store.dispatch("createToken", this.model)
- 这段代码的意思是调用 store仓库的actions.js中的createToken方法
![](https://img-blog.csdnimg.cn/20210625223458742.png)
/** * 创建新的客户端令牌 */ createToken: async ({ commit }, { username, password }) => { //请求后台登录接口 const res = await TokenService.userLogin({ phone: username.trim(), password: password.trim() }); console.log(res); //判断结果不等于1,登录失败 if (res.state !== 1) { return Promise.resolve(res); } //获取到content const result = res.content; //将token保存 commit(CHANGE_SESSION, { accessToken: result.access_token }); return res; }, |
import { TokenService, UserService } from "../services"; |
![](https://img-blog.csdnimg.cn/20210625223458692.png)
//登录请求 async ES6语法, 作用: 发送异步请求 export const userLogin = async (data) => { //await 表示等待接收返回的数据 return await PostRequest(`${process.env.VUE_APP_API_FAKE}/user/login${Serialize(data)}`) } |
1.2 动态获取用户菜单
1.2.1 流程分析
1) 在我们登录成功后, 会立即发送第二个请求, 来获取用户的菜单权限列表
![](https://img-blog.csdnimg.cn/20210625223458746.png)
2) 在actions.js 中完成请求后台接口 获取数据的操作
/** * 获取当前登录用户权限 */ getUserPermissions: async ({ commit }) => { //1.请求后台 获取当前用户的权限 const res = await UserService.getUserPermissions(); //2.判断 if (!res.success) { //获取失败直接返回 false return res.success; } //3.获取数据成功,取出菜单 与 资源列表 const { menuList, resourceList } = res.content; //4.下面的代码 就是在生成树形结构的菜单 let menus = []; const formatMenu = treeData => { if (treeData.length > 0) { return treeData.map(item => formatMenu(item)); } const result = {}; //shown等于表示可以显示,将内容保存 if (treeData.shown == 1) { result.id = treeData.id; result.text = treeData.name; result.label = treeData.name; result.name = treeData.href; result.icon = treeData.icon; result.shown = treeData.shown; } else { return ""; } //获取子节点 if (treeData.subMenuList) { result.children = []; treeData.subMenuList.forEach(item => { formatMenu(item) && result.children.push(formatMenu(item)); }); if (result.children.length === 0) { delete result.children; } } return result; }; const memusMap = {}; const splapMenu = treeData => { if (treeData.length > 0) { return treeData.map(item => splapMenu(item)); } const result = {}; result.id = treeData.id; result.text = treeData.name; result.label = treeData.name; result.name = treeData.href; result.icon = treeData.icon; result.shown = treeData.shown; result.name && (memusMap[result.name] = result); if (treeData.subMenuList) { result.children = []; treeData.subMenuList.forEach(item => { result.children.push(splapMenu(item)); }); } return result; }; splapMenu(menuList); menus = formatMenu(menuList); commit(CHANGE_SIDERBAR_MENU, menus); return { menus, resourceList, menuList, memusMap }; }, |
1.3 验证Token
1.3.1 导航守卫
在执行路由之前先执行的一些钩子函数,比如验证用户是否有权限之类的操作,就需要使用.
1) authorize.js 中配置了导航守卫,来对用户的登录进行限制
// 导航守卫 to要访问的url, from从哪个路径跳转过来, next() 放行 router.beforeHooks.unshift((to, from, next) => { //不需要验证直接放行 if (!to.meta.requireAuth) return next(); //需要验证token,调用 store中的checkToken方法 store.dispatch("checkToken").then(valid => { //判断是否存在token if (valid) { //发送请求到后台,在后台再次判断token是否存在 store.dispatch("getUserPermissions").then(res => { if (!res) { //失效 清除token store.dispatch("deleteToken"); //跳转到登录页面 return next({ name: "ToLogin" }); } //token正确, 导航到对应的页面 const { memusMap } = res; if (memusMap.Courses && to.name === "Home") { return next(); } else if (memusMap[to.name]) { return next(); } else if (Object.keys(memusMap).length > 0) { return next({ name: memusMap[Object.keys(memusMap)[0]].name }); } else { next({ name: "PermissionDenied" }); } }); return next(); } // unauthorized console.log("Unauthorized"); //用户没有登录 跳转到登录页面 next({ name: "Login", query: { redirect: to.fullPath } }); }); }); |
checkToken: async ({ commit, getters }) => { //取出token const token = getters.session.accessToken; if (!token) { //不可用 return Promise.resolve(false); } return Promise.resolve(true); }, |
2) 在actions.js 中检查token是否可用
checkToken: async ({ commit, getters }) => { //取出token const token = getters.session.accessToken; if (!token) { //不可用 return Promise.resolve(false); } return Promise.resolve(true); }, |