在配置有菜单权限的系统中,根据菜单显示
来控制是否能访问某页面,能看得到但菜单就能点击访问,但如果直接访问页面路径,则跳出了菜单控制的范畴,所以要在每次访问页面前,对当前访问对路径进行权限校验,才能达到权限控制的目的
(一)在页面登录后,把账户权限信息缓存在localStorage中
this.axios
.post(`${request.URL.LOGIN}`, {
...
})
.then(res => {
...
localStorage.setItem("userInfo", JSON.stringify(res.data));
...
})
(二)在路由配置文件中,把需要权限校验的页面增加 forbidden: true
const router = new Router({
routes: [
{
path: "/",
name: "Login",
component: () => import("@/pages/login/login.vue"),
meta: { forbidden: false }
},
{
path: "/pharmacyList",
name: "pharmacyList",
component: () => import("@/pages/organizationManagement/pharmacyList.vue"),
meta: { forbidden: true }
},
{
path: "/403",
name: "403",
component: () => import("@/pages/403.vue"),
meta: { forbidden: false }
},
]
});
(三)增加403页面
<template>
<div class="forbidden">
<div
style="
text-align: center;
margin-top: 100px;
font-size: 20px;"
>
403 您无权访问该页面,请联系管理员
</div>
<div class="btn">
<el-button size="small" type="primary" plain @click="toHome"
>返回首页</el-button
>
</div>
</div>
</template>
<script>
export default {
methods: {
toHome() {
this.$router.push("/");
}
}
};
</script>
<style scoped>
.forbidden {
display: flex;
flex-direction: column;
justify-content: center;
}
.btn {
display: inline-flex;
margin-top: 50px;
justify-content: center;
}
</style>
(四)在项目的main.js文件中,写入路由守卫的逻辑
根据项目存取的实际情况,主要思路就是判断当前访问的路径是否设置在菜单权限中
以下为我项目中的实际判断情况,由于历史原因,是根据菜单名称进行判断,新项目如果能在权限控制时,保存菜单路径更好
router.beforeEach((to, from, next) => {
let userInfo = localStorage.getItem("userInfo")
? JSON.parse(localStorage.getItem("userInfo"))
: {};
// 首页无须校验是否登录
if (!VueCookies.get("acl_t") && to.path != "/") {
next({ path: "/", query: { noToken: true } });
}
// 非首页的权限判断
else {
// 如果当前不是管理员,并且访问的路径没有设置forbidden=false,需要判断权限
if (userInfo.ext != "root" && to.meta.forbidden != false) {
// 获取用户设置的路由权限,根据项目中存取的实际情况获取
let links = userInfo.links;
links = links ? JSON.parse(links).home : [];
let data = [];
for (let l in links) {
data.push(...links[l].children);
}
// 路由权限中全部可以访问的名称集合
data = data.map(d => {
return d.name;
});
// 路径名称查找关系
let accountManagementData = [];
for (let ac in accountManagement) {
accountManagementData.push(...accountManagement[ac].children);
}
// 找出当前访问的页面名称
let result = accountManagementData.find(ac => {
return ac.path == to.name;
});
// 如果页面并没有标题,可能是详情页,不需要判断
if (result) {
// 如果权限里面有当前访问的名称
if (data.includes(result.name)) {
next();
} else {
next("/403");
}
} else {
next();
}
} else {
next();
}
}
});
以上,根据路由守卫实现权限控制完成,其中有几点注意事项
1. 对页面进行权限控制前,先判断是否登录,如未登录,先跳转到登录页面,而非403页面
2. 登录后的权限信息,应缓存在localStorage中,如缓存在state中,则有可能出现用户新开一个浏览器窗口,登录凭证还在,但获取不到权限控制数据,导致判断错误