前景:一个系统平台,针对不同用户登录做了一个权限功能,首先展示的菜单,事先在route.js中配置好,根据后台返回的菜单名称,按需展示对应菜单。但是当时忘记做一个判断,若一个用户已经登录,虽然菜单未展示比如权限管理页面,但对方知道权限管理页面地址,在地址栏中直接输入地址,可直接访问。因为在路由中没有做拦截判断。

下面上代码:
router文件夹中有两个文件,一个是index.js,一个是route.js
router/route.js

import basic from "@/pages/basic/basic"  // 这是一个公共页面,每个页面都用的到
export const routes = [
	{
		name: 'home',
		title: 'home',
		path: '/home',
		component: basic,
		redirect: '/home/home',
		children: [
			{
				name: 'home',
				title: 'home',
				path: '/home/home',
				component: home
			}
		]
	},
	{
		name: 'menu',
		title: 'menu',
		path: '/menu',
		component: basic,
		redirect: '/menu/menu1',
		children: [
			{
				name: 'menu1',
				title: 'menu1',
				path: '/menu/menu1',
				meta: { requiresAuth: true }, // 若是需要校验权限的页面,需在该页面配置此属性
				component: menu1
			},
			{
				name: 'menu2',
				title: 'menu2',
				path: '/menu/menu2',
				meta: { requiresAuth: true },
				component: menu2
			},
			{
				name: 'menu3',
				title: 'menu3',
				path: '/menu/menu3',
				component: menu3
			}
		]
	},
	{
		name: 'system',
		title: 'system',
		path: '/system',
		component: basic,
		redirect: '/system/role',
		children: [
			{
				name: 'role',
				title: 'role',
				path: '/system/role',
				meta: { requiresAuth: true },
				component: role
			}
		]
	}
]
exportconst login = {
	name: 'login',
	title: 'login',
	path: '/',
	component: login,
}
export const routers = [
	...routes,
	login
]

router/index.js

import Vue from 'vue'
import Router from 'vue-router'
import { store } from '@/store/index'
import { Message } from "element-ui"  // 弹框组件
import Cookies from 'js-cookie'
import { routers } from '@/router/route';

Vue.use(Router)

const router = new Router({
	mode: 'history',
	routes: routers
})

router.beforeEach((to, from, next) => {
 	if (Cookies.get('userNo')) {// 判断是否缓存中有userNo,这是一个工号,没有跳回登录页
 		if (to.matched.some(res => res.meta.requiresAuth)){
			// 此处是根据我在路由中添加的meta.requiresAuth属性,
			// 若访问的页面中有我这项属性,那么当用户直接访问该页面时,会进入此项判断。
			// 下面我要在这里判断,用户访问的to.path,跟我菜单中的path是否一致,
			// 若一致,那么该登录者可以访问此页面,
			// 若不一致,将跳出登录页,或提示用户无权限访问该页面
			let menuListStatus = store.state.menuListStatus;// 接口返回可以访问的菜单,存储在vuex中
			let menuList = store.state.menuList;// 根据返回的菜单跟我路由中配置好的router数组做处理,把不需要展示的菜单过滤掉,存储在vuex中
			if (menuListStatus && menuListStatus.length != 0) {
				if (menuList && menuList.length != 0) {
					let isMenu = deepQuery(menuList,to.path);
					if (isMenu) {// 若存在,继续访问
						next();
					} else {
						Message({
                               message: '无权限访问',
                               type: "warning"
                           });
                           next('/');
					}
				} else {
					next();
				}
			} else {
				next();
			}
		} else {// 若没上面的判断,说明是访客组就可以访问的页面
			next();
		}

	} else {
		next({ path: '/'})
	}
})

// 查找菜单数组中path是否存在
function deepQuery(tree,path) {
    var isGet = false;
    var retNode = null;
    function deepSearch(tree,path){
        for(var i = 0; i<tree.length; i++) {
            if(tree[i].children && tree[i].children.length>0) {
                deepSearch(tree[i].children,path);
            }
            if(path === tree[i].path || isGet) {
                isGet||(retNode = tree[i]);
                isGet = true;
                break;
            }
        }
    }
    deepSearch(tree,path);
    return retNode;
}

store/index.js文件如下

import Vue from 'vue'
import Vuex from 'vuex'
import createPersistedState from 'vuex-persistedstate'
Vue.use(Vuex)

var store = new Vuex.Store({
	state: {
		menuListStatus: [],
		menuList: []
	},
	mutations: {
		saveMenu (state,data) {
			state.menuListStatus = data;
		},
		saveMenuList (state,data) {
			state.menuList= data;
		}
	}
})

我菜单请求回来的数据:

import _ from 'lodash' //这个自行科普吧
import { store } from '@/store/index'
import { routers } from '@/router/route';
// 后台返回只有菜单名字,所以要处理一下
var menuList = [
	{
		id: 1,
		title: 'home'
	},
	{
		id: 2,
		title: 'menu1'
	},
	{
		id: 3,
		title: 'menu2'
	},
	{
		id: 4,
		title: 'menu3'
	}
]
// 把拿到的菜单存储在vuex中
store.commit('saveMenulistStatus',menuList);

// 下面要把拿到的菜单跟router中的数组做处理
function accessRecursive(arr) {// 处理拿到的菜单与路由处理
   letflag = false
   let jsonArr = menuList;
   for(var I  = 0; I < arr.length; I++){
       var item = arr[I]
       if (item.children) {
           item.allow = accessRecursive(item.children)
       }
       if (item.allow || jsonArr.some(ele => ele.title === item.title)) {
           item.allow = true
       }
       flag = flag || item.allow
       if (!item.allow) {
           arr.splice(I, 1)
           I--
       }
   }
   return flag
},
let routeArr =_.cloneDeep(routers);
let list = [];
list = accessRecursive(routeArr);
// 处理后的菜单放入vuex中
store.commit('saveMenuList',list)

综上所述,根据后台返回给我的菜单中没有role这个页面,所以该用户登录之后,若在地址栏中输入/system/role,是无法访问的。

Logo

前往低代码交流专区

更多推荐