preface
Recently, I suddenly saw the background management system written before, and felt that the control of permissions was not well written, so I made a transformation. Here I record the problems and permissions logic encountered in the transformation, hoping to help you a little.
Project preview address: Vue Antd Admin, interested can have a look
Login Permission Control
After clicking login, I used mock mock data, searched in user constant list by user name, returned corresponding user information and token, and then carried token in request header. If no token exists or token is invalid, login is required. Strictly speaking, During login, the password and returned token need to be encrypted and cannot be passed in plain text. This is not done because it is my own project.
After login, the token information and userInfo information are stored in the VUex and Session (of course, you can not save the VUex, depending on the individual). The most important information in the returned information is the roleIds field, which represents the current user has the permission ID
Example Login result:
token: "admin2022012030427", userInfo: { date: "2020-10-13", id: 472467715762, key: "admin", label: "Young people do not speak martial virtue ", location: "Wuhan", password: "123456", position:" mixed yuan Tai Chi door master ", role: "admin", roleIds: "1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36", roleString: "Admin" skill: "admin" text: "admin" username: "admin"}Copy the code
Request headers carry tokens:
service.interceptors.request.use(config => {
if (store.getters.token) {
config.headers['authorization'] = store.getters.token;
}
return config;
});
Copy the code
Menu permission Control
Implementation approach
There are two common menu permission control methods, front-end control and back-end control, but it is best to control the front-end, otherwise you want to add a menu must also say and back-end, let him add a menu, and return to the fear of being dominated by the back-end… However, whether it is front-end control or back-end control, it is necessary to get the menu list corresponding to the login user, and then add the route through the addRoutes method of vue-Router.
[‘admin’,’test’] [‘admin’,’test’] [‘admin’,’test’] [‘admin’,’test’] [‘admin’,’test’] [‘admin’,’test’] [‘admin’,’test’] Therefore, each menu is given a corresponding roleId in this modification. Then, the menu corresponding to the current user is obtained by comparing the roleIds in the login and the roleIds in the routing table.
export const asyncRoutes = [ { path: '/', component: Layout, redirect: '/index', hidden: true, children: [ { name: 'index', path: '/index', Component: () => import('@/views/index/index'), meta: {role: 1, title: 'home ', icon: 'dashboard' } }, { name: 'icon', path: '/icon', component: () => import('@/views/icon/index'), meta: { role: 2, title: 'icon', 'icon'}},]Copy the code
beforeEach
We also need a hook for vue-router. BeforeEach this global guard has three arguments :to,from, and next
to
: the page you want to jump toroute
informationfrom
: of the current pageroute
informationnext
Use this method to resolve the resolve hook, otherwise the page jump will not succeed
For example, if you switch from page A to page B, page A is from, and page B is to
router.beforeEach( (to, from, next) => { const localId = localStorage.getItem('userId'); If (to.name === 'login') {if (localId) {next({... to, replace: true }); } else {// No cache, jump to login page next('/login'); }}});Copy the code
We can separate out beforeEach, create a permission.js file, and then import it in main.js
Access control
This requires careful debugging. If it is judged that the writing is not complete, it is easy to have an endless loop, you can interrupt the debugging point carefully. Permission.js is roughly as follows:
router.beforeEach(async (to, from, next) => { document.title = getPageTitle(to.meta.title); //title Adds the current menu name const isLogin = getCache('TOKEN'); If (to.path == '/login') {// Next next() if (to.path == '/login'); } else { if (! IsLogin) {// If you are not logged in, forcibly jump to login, prevent forcible input address jump to next('/login'); } else { const route = store.state.permission.routes; If (route.length > 0) {next next(); } else {/ / if you do not generate const the userInfo = store. State. The user. The accountInfo; Try {const {roleIds} = userInfo; const accountRoute = await store.dispatch('permission/getRoute', roleIds); Router. AddRoutes (accountRoute); If (from. Path == '/login') {// Next (accountRoute[0].children[0].path); } else { next({ ... to, replace: true }); } } catch (error) { console.log(error); Message. error(' failed to get user information '); next('/login'); }}}}});Copy the code
Get routing menu
Routing table inside can set two kinds of routes, one is not need permission control, such as: login page, 404 page, etc., one is need permission control; Here basRoute is the basic route, asyncRoutes is the route that requires permission control, and here is the permission file of store. The main function is to obtain the route menu according to the roleIds of the logged-in user
import { baseRoute, asyncRoutes } from '@/router'; const state = { routes: [] }; const mutations = { SET_ROUTE(state, route) { state.routes = baseRoute.concat(route); }}; Const Actions = {getRoute({commit}, role) {return new Promise((resolve, resolve) reject) => { let accessedRoutes = []; accessedRoutes = filterAsyncRoute(asyncRoutes, role); commit('SET_ROUTE', accessedRoutes); resolve(accessedRoutes); }); }}; Export function filterAsyncRoute(routes, role) {let arr = []; routes.forEach(item => { const temp = { ... item }; if (hasChildren(temp, role)) { if (temp.children) { temp.children = filterAsyncRoute(temp.children, role); } arr.push(temp); }}); return arr; } role export function hasChildren(route, role) {let roleIds = role.split(','); if (route.meta && route.meta.role) { return roleIds.includes(String(route.meta.role)); } else { return true; } } export default { namespaced: true, state, mutations, actions };Copy the code
Sidebar display
Here we have obtained the corresponding permissions of the user, and the next step is to render it to the sidebar. Here we use recursive traversal, because the antD root directory will not render if there is a div tag, so we use the method of functional components here
<a-menu :mode="mode" :inline-collapsed="! collapsed" theme="dark" :selectedKeys="[$route.path]" :open-keys="openKeys" @openChange="changeOpen" > <template v-for="item in baseRoute"> <menu-item v-if="! item.children && ! item.hidden" :key="item.path :currentRoute="item" /> <template v-else v-for="temp in item.children"> <menu-item v-if="! temp.children" :key="temp.path" :currentRoute="temp" /> <sub-menu v-else :key="temp.path" :currentRoute="temp"></sub-menu> </template> </template> </a-menu>Copy the code
subMenuItem.vue <a-sub-menu :key="props.currentRoute.path"> <template slot="title"> <svg-icon :icon="props.currentRoute.meta.icon" v-if="props.currentRoute.meta.icon"> </svg-icon> <span style="margin-left:16px" class="menu-title">{{ props.currentRoute.meta.title }}</span> </template> <template v-for="item in props.currentRoute.children"> <menu-item v-if="! item.children" :key="item.path" :currentRoute="item" /> <sub-menu v-else :key="item.path" :currentRoute="item" /> </template> </a-sub-menu>Copy the code
Role Management Menu
User and role bindings, roles and menu binding, so will need to modify the roles corresponding to modify menu tree, there’s a little details need to pay attention to, because the tree is to be checked if the parent node, all child nodes will be selected, but in practice, we may need to check the parent node, but only checked a child node, So you have to control it individually, and you have to recurse
Mounted (){if (this.role) {// Echo this. } else { this.checkKeyList = []; Const allRoute = this.getrouteid (data); const allRoute = this.getrouteid (data); const allRoute = this.getrouteid (data); Let roleRoute = this.role. Split (','); // Let roleRoute = this.role. let newRoute = []; ForEach (item => {roleroute. forEach(val => {if (item == val) {newroute.push (val); }}); }); this.checkKeyList = newRoute; Check}, getRouteId(routes, role = null) {const res = []; routes.forEach(item => { if (item.children && item.children.length > 0) { res.push(... this.getRouteId(item.children, item.meta.role)); } else if (item.meta && item.meta.role) { res.push(String(item.meta.role)); } else if (role) { res.push(String(role)); }}); return res; },Copy the code
Page button control
The truth is the same as the menu, but also can give the page button an ID, according to the user information roleIds contain this ID, to control the display and hide, but need to code annotation and documentation is complete, or the next button does not know what the user can see, debugging trouble.
Project description
Vue Antd Admin based on vue-Cli4.x +vuex+ ant-design-Vue development of background management system, including permission management, a variety of layout, skin function, visual drag, large screen display, user multi-role and some other functions, interested can see.
The last
To here, the system background management authority has been completed, the front control authority method has many kinds, can be used according to the specific situation, this time on the admin system modified role authority, users add multiple roles, skin and external chain and other functions, interested can take a look
Other articles
-
Vii. Using VUE + ANTD to build background Management System (Requirements Analysis and Construction)
-
Vi. Remember a Vue3.0 taste \
-
V. Remember to build a VUE project with Webpack once
-
Remember to refactor the project with TS +vuecli4 once
-
Echarts+Amap to achieve the click drilling function
-
Vue keep-alive stomp pit, delete keep-alive cache
\