图片存放网站做链接,东莞网络推广教程,原型设计网站,泰安搜索引擎优化招聘角色权限
角色权限#xff0c;简单来说就是登录的用户能看到系统的哪些页面#xff0c;不能看到系统的哪些页面。一般是后台管理系统才会涉及到如此复杂的角色权限。
对于 vue 技术栈#xff0c;实现角色权限一般有两种方式。
第一种是利用 beforeEach 全局前置守卫。
第…角色权限
角色权限简单来说就是登录的用户能看到系统的哪些页面不能看到系统的哪些页面。一般是后台管理系统才会涉及到如此复杂的角色权限。
对于 vue 技术栈实现角色权限一般有两种方式。
第一种是利用 beforeEach 全局前置守卫。
第二种是利用 addRoutes 方法。
我们先来看看第一种
通过 beforeEach 实时监测用户权限
这种方案的核心就是首先在 routes 里面事先定义好路由的权限然后在 beforeEach 全局前置守卫里面进行权限逻辑判断。看用户所拥有的角色和我们配置在路由里面的 roles 是否相匹配。匹配则允许进入不匹配则重定向到无权限提示页面。
定义 routes
首先我们定义好系统的路由对于非首页我们一般都会使用路由懒加载。
在 meta 里面可以定义我们需要的元数据这里需要加上我们路由的角色roles。也就是说进入该路由用户所需要具备的角色权限。如果没定义则代表任意角色都能进入。
js
复制代码
// router/routes.jsimport Home from ../views/Home.vue;const routes [{path: /,name: Home,component: Home,meta: {needLogin: false, // 不需要登录title: 首页,},},{path: /about, name: About,component: () import(/* webpackChunkName: about */ ../views/About.vue), // 路由懒加载meta: {needLogin: true, // 需要登录title: 关于,roles: [admin, manage], // 该页面只有admin和普通管理员才能进入},},{path: /nopermission, // 没权限就进入该页面name: NoPermission,component: () import(/* webpackChunkName: nopermission */ ../views/NoPermission.vue), // 路由懒加载meta: {needLogin: true, // 需要登录title: 暂无权限,},},{path: /userlist, name: UserList,component: () import(/* webpackChunkName: userlist */ ../views/UserList.vue), // 路由懒加载meta: {needLogin: true, // 需要登录title: 用户管理,roles: [admin], // 该页面只有admin才能进入},},{path: /login,name: Login,component: () import(/* webpackChunkName: login */ ../views/Login.vue), // 路由懒加载meta: {needLogin: false, // 不需要登录title: 登录,},},
];export default routes;实例化 Router
然后创建路由vue2和vue3创建路由的时候稍有区别但是在路由鉴权那块是通用的。
js
复制代码
// router/index.js// vue2 写法
import VueRouter from vue-router;
import routes from ./routesconst router new VueRouter({mode: history,base: process.env.BASE_URL,routes,
});// vue3 写法
import { createRouter, createWebHistory } from vue-router;
import routes from ./routesconst router createRouter({history: createWebHistory(process.env.BASE_URL),routes,
});定义路由拦截鉴权逻辑
创建好路由后我们可以来定义路由拦截的逻辑了主要通过 beforeEach 全局前置守卫。因为只要页面发生跳转都会进入 beforeEach 全局前置守卫。 这里的核心逻辑就是判断前往的页面是否需要登录需要登录就进一步判断当前系统是否有token没有token则重定向到登录页 如果有token则进一步判断是否有用户信息如果没有用户信息就获取用户信息 有了用户信息后再判断进入页面需要的角色是否和用户信息里面的角色相匹配匹配则进入页面不匹配则进入系统的无权限提示页面。 js
复制代码
// router/index.js// vue2和vue3通用
router.beforeEach(async (to, from, next) {// 如果需要登录if (to.meta.needLogin) {// 获取tokenconst token localStorage.getItem(token);// 如果有token 则直接放行if (token) {// 获取用户信息从store里面获取let userInfo store.getters[getUserInfo];// 如果没有用户信息就获取用户信息if (!userInfo) {userInfo await store.dispatch(getUserInfoAction);}// 如果页面需要权限并且用户角色不满足则去无权限提示页if (to.meta.roles !to.meta.roles.includes(userInfo.role)) {return next(/nopermission);}next();} else {// 否则去登录页next(/login);}} else {// 不需要登录则直接放行next();}
});// 修改标题的工作可以放在全局后置守卫
router.afterEach((to, from) {if (to.meta.title) {document.title to.meta.title;}
});我们再来看看 store 的逻辑
js
复制代码
import { createStore } from vuex;export default createStore({state: {userInfo: null,},getters: {getUserInfo: (state) state.userInfo,},mutations: {setUserInfo(state, payload) {state.userInfo payload;},},actions: {async getUserInfoAction({ commit }) {// 模拟后端获取用户信息的apiconst getUserInfoApi () {return Promise.resolve({ role: manage, name: jack }); // 假设角色为 manage};const userInfo await getUserInfoApi();commit(setUserInfo, userInfo);return userInfo;},},
});使用
创建完路由后需要在 main.js 导入使用
js
复制代码
import router from ./router;// vue2写法
new Vue({router,render: (h) h(App),
}).$mount(#app);// vue3写法
const app createApp(App);
app.use(router).mount(#app);
在没登录的情况下去about和userlist页面都会重定向到登录页。
给本地添加token 模拟登录完成后因为用户信息角色是 manage所以去 about 是没问题的去 userlist 则会重定向到没有权限页面。
总结
优点
实现简单路由的权限在 meta 的 roles 里面配置。用户信息里面只需要包含当前用户的角色。
缺点
系统所拥有的角色必须事先知道然后以死代码的形式配置在 routes 里面不支持动态添加角色。适用于小型角色固定的系统。
通过 addRoutes 动态添加路由
这种方案的核心就是调用后端接口返回当前用户角色所拥有的菜单格式化成路由后通过 addRoutes 将这些路由动态添加到系统。
定义 routes
因为路由从后端获取所以这里我们只需要定义基本通用路由也就是不涉及到权限的路由。比如登录页、没权限页、首页。
js
复制代码
import Home from ../views/Home.vue;const routes [{path: /,name: Home,component: Home,meta: {title: 首页,},},{path: /nopermission, // 没权限就进入该页面name: NoPermission,component: () import(/* webpackChunkName: nopermission */ ../views/NoPermission.vue), // 路由懒加载meta: {title: 暂无权限,},},{path: /login,name: Login,component: () import(/* webpackChunkName: login */ ../views/Login.vue), // 路由懒加载meta: {title: 登录,},},
];export default routes;实例化 Router
然后创建路由vue2和vue3创建路由的时候稍有区别。
js
复制代码
// router/index.js// vue2 写法
import VueRouter from vue-router;
import routes from ./routesconst router new VueRouter({mode: history,base: process.env.BASE_URL,routes,
});// vue3 写法
import { createRouter, createWebHistory } from vue-router;
import routes from ./routesconst router createRouter({history: createWebHistory(process.env.BASE_URL),routes,
});定义路由拦截鉴权逻辑
创建好路由后我们就可以定义动态添加路由的逻辑啦。 这里的核心逻辑就是判断前往的页面是否在白名单内不在白名单就进一步判断当前系统是否有token没有token则重定向到登录页 如果有token则进一步判断是否有用户菜单信息如果没有用户菜单信息就获取用户菜单信息 有了用户菜单信息后就先将菜单信息转换成前端路由需要的格式然后通过addRoutes方法将路由动态添加到系统。 当用户前往不存在的路由时路由的 name 属性会是 undefined因此就重定向到无权限提示页面 js
复制代码
// router/index.js// vite创建的项目 使用这种方法实现动态加载
const modules import.meta.glob(../views/*.vue);// 转换成 vue-router 需要的格式
const transformRoute (menus) {return menus.map((menu) {return {path: menu.path,name: menu.name,component: modules[menu.component],meta: {title: menu.title,},};});
};// vue3需要手动实现该方法
const addRoutes (routes) {routes.forEach((route) {router.addRoute(route);});
};// 白名单页面不需要权限
const whiteLists [/login, /];router.beforeEach(async (to, from, next) {// 是否是白名单if (!whiteLists.includes(to.path)) {// 获取tokenconst token localStorage.getItem(token);// 如果有tokenif (token) {// 获取用户菜单信息从store里面获取let userMenus store.getters[getUserMenus];// 如果没有用户菜单信息就获取用户菜单信息if (!userMenus) {userMenus await store.dispatch(getUserMenuAction);// 菜单转成路由const userRoute transformRoute(userMenus);// 动态添加路由 vue2 和 vue3 有细微差别// vue2// router.addRoutes(userRoute)// vue3// 因为 vue3 移除了 router.addRoutes()方法所以需要手动实现addRoutes方法。addRoutes(userRoute);return next({ ...to });}// 有name说明路由存在否则说明没有该路由if (to.name) {next();} else {// 去无权限页面next(/nopermission);}} else {// 否则去登录页next(/login);}} else {// 是白名单则直接进入next();}
});// 修改标题的工作可以放在全局后置守卫
router.afterEach((to, from) {if (to.meta.title) {document.title to.meta.title;}
});我们再来看看 store 的逻辑
js
复制代码
import { createStore } from vuex;export default createStore({state: {userMenus: null,},getters: {getUserMenus: (state) state.userMenus,},mutations: {setUserMenus(state, payload) {state.userMenus payload;},},actions: {async getUserMenuAction({ commit }) {// 模拟后端获取用户菜单信息apiconst getUserMenuApi () {// 假设只有about菜单return Promise.resolve([{path: /about,name: About,component: ../views/About.vue,title: 关于,},]);};const userMenus await getUserMenuApi();commit(setUserMenus, userMenus);return userMenus;},},
});使用
创建完路由后需要在 main.js 导入使用
js
复制代码
import router from ./router;// vue2写法
new Vue({router,render: (h) h(App),
}).$mount(#app);// vue3写法
const app createApp(App);
app.use(router).mount(#app);
在没登录的情况下去about和userlist页面会重定向到登录页。
给本地添加token模拟登录完成后因为用户有about的菜单所以去 about 页面是没问题的去 userlist 页面则会重定向到没有权限页面。
总结
优点
系统角色可以不固定支持动态添加角色。适用于后台大型管理系统。
缺点
实现相对复杂而且需要后端配合的更多。
总结
第一种通过 beforeEach 实时监测用户权限的方式优势是实现简单路由的权限在 meta 的 roles 里面配置。用户信息里面只需要包含当前用户的角色。缺点呢也很明显系统所拥有的角色必须事先知道然后以死代码的形式配置在 routes 里面不支持动态添加角色。笔者觉得如果是做角色固定的系统是非常好的比如什么图书管理系统、教师管理系统等。
第二种通过 通过 addRoutes 动态添加路由实现角色权限的方式优势是系统角色可以不固定支持动态添加角色。很适用于后台大型管理系统可以实时创建角色分配菜单。
当然、缺点就是实现起来比较复杂需要后端一起参与设计。