原文转自:点我

页面权限控制

页面权限控制是什么意思呢?

就是一个网站有不同的角色,比如管理员和普通用户,要求不同的角色能访问的页面是不一样的。如果一个页面,有角色越权访问,这时就得做出限制了。

Vue 动态添加路由及生成菜单这是我写过的一篇文章,
通过动态添加路由和菜单来做控制,不能访问的页面不添加到路由表里,这是其中一种办法。

另一种办法就是所有的页面都在路由表里,只是在访问的时候要判断一下角色权限。如果有权限就让访问,没有权限就拒绝,跳转到 404 页面。

思路:

在每一个路由的 meta 属性里,将能访问该路由的角色添加到 roles 里。用户每次登陆后,将用户的角色返回。然后在访问页面时,把路由的 meta 属性和用户的角色进行对比,如果用户的角色在路由的 roles 里,那就是能访问,如果不在就拒绝访问。

代码示例:

路由信息

routes: [
{
path: '/login',
name: 'login',
meta: {
roles: ['admin', 'user']
},
component: () => import('../components/Login.vue')
},
{
path: 'home',
name: 'home',
meta: {
roles: ['admin']
},
component: () => import('../views/Home.vue')
},
]

页面控制

// 假设角色有两种:admin 和 user
// 这里是从后台获取的用户角色
const role = 'user'
// 在进入一个页面前会触发 router.beforeEach 事件
router.beforeEach((to, from, next) => {
if (to.meta.roles.includes(role)) {
next()
} else {
next({path: '/404'})
}
})

登陆验证

网站一般只要登陆过一次后,接下来该网站的其他页面都是可以直接访问的,不用再次登陆。
我们可以通过 token 或 cookie 来实现,下面用代码来展示一下如何用 token 控制登陆验证。

 
router.beforeEach((to, from, next) => {
// 如果有token 说明该用户已登陆
if (localStorage.getItem('token')) {
// 在已登陆的情况下访问登陆页会重定向到首页
if (to.path === '/login') {
next({path: '/'})
} else {
next({path: to.path || '/'})
}
} else {
// 没有登陆则访问任何页面都重定向到登陆页
if (to.path === '/login') {
next()
} else {
next(`/login?redirect=${to.path}`)
}
}
})

Vue 动态添加路由及生成菜单

写后台管理系统,估计有不少人遇过这样的需求:根据后台数据动态添加路由和菜单。
为什么这么做呢?因为不同的用户有不同的权限,能访问的页面是不一样的。
在网上找了好多资料,终于想到了解决办法。

动态生成路由

利用 vue-router 的 addRoutes 方法可以动态添加路由。

先看一下官方介绍:

router.addRoutes

router.addRoutes(routes: Array<RouteConfig>)

动态添加更多的路由规则。参数必须是一个符合 routes 选项要求的数组。

举个例子:

const router = new Router({
routes: [
{
path: '/login',
name: 'login',
component: () => import('../components/Login.vue')
},
{path: '/', redirect: '/home'},
]
})

上面的代码和下面的代码效果是一样的

const router = new Router({
routes: [
{path: '/', redirect: '/home'},
]
}) router.addRoutes([
{
path: '/login',
name: 'login',
component: () => import('../components/Login.vue')
}
])

在动态添加路由的过程中,如果有 404 页面,一定要放在最后添加,否则在登陆的时候添加完页面会重定向到 404 页面。

类似于这样,这种规则一定要最后添加。

{path: '*', redirect: '/404'}

动态生成菜单

假设后台返回来的数据长这样

// 左侧菜单栏数据
menuItems: [
{
name: 'home', // 要跳转的路由名称 不是路径
size: 18, // icon大小
type: 'md-home', // icon类型
text: '主页' // 文本内容
},
{
text: '二级菜单',
type: 'ios-paper',
children: [
{
type: 'ios-grid',
name: 't1',
text: '表格'
},
{
text: '三级菜单',
type: 'ios-paper',
children: [
{
type: 'ios-notifications-outline',
name: 'msg',
text: '查看消息'
},
{
type: 'md-lock',
name: 'password',
text: '修改密码'
},
{
type: 'md-person',
name: 'userinfo',
text: '基本资料',
}
]
}
]
}
]

来看看怎么将它转化为菜单栏,我在这里使用了 iview 的组件,不用重复造轮子。

<!-- 菜单栏 -->
<Menu ref="asideMenu" theme="dark" width="100%" @on-select="gotoPage"
accordion :open-names="openMenus" :active-name="currentPage" @on-open-change="menuChange">
<!-- 动态菜单 -->
<div v-for="(item, index) in menuItems" :key="index">
<Submenu v-if="item.children" :name="index">
<template slot="title">
<Icon :size="item.size" :type="item.type"/>
<span v-show="isShowAsideTitle">{{item.text}}</span>
</template>
<div v-for="(subItem, i) in item.children" :key="index + i">
<Submenu v-if="subItem.children" :name="index + '-' + i">
<template slot="title">
<Icon :size="subItem.size" :type="subItem.type"/>
<span v-show="isShowAsideTitle">{{subItem.text}}</span>
</template>
<MenuItem class="menu-level-3" v-for="(threeItem, k) in subItem.children" :name="threeItem.name" :key="index + i + k">
<Icon :size="threeItem.size" :type="threeItem.type"/>
<span v-show="isShowAsideTitle">{{threeItem.text}}</span>
</MenuItem>
</Submenu>
<MenuItem v-else v-show="isShowAsideTitle" :name="subItem.name">
<Icon :size="subItem.size" :type="subItem.type"/>
<span v-show="isShowAsideTitle">{{subItem.text}}</span>
</MenuItem>
</div>
</Submenu>
<MenuItem v-else :name="item.name">
<Icon :size="item.size" :type="item.type" />
<span v-show="isShowAsideTitle">{{item.text}}</span>
</MenuItem>
</div>
</Menu>

代码不用看得太仔细,理解原理即可,其实就是通过三次 v-for 不停的对子数组进行循环,生成三级菜单。

动态菜单这样就可以实现了。

动态路由,因为上面已经说过了用 addRoutes 来实现,现在看看具体怎么做。

首先,要把项目所有的页面路由都列出来,再用后台返回来的数据动态匹配,能匹配上的就把路由加上,不能匹配上的就不加。 最后把这个新生成的路由数据用 addRoutes 添加到路由表里。

const asyncRoutes = {
'home': {
path: 'home',
name: 'home',
component: () => import('../views/Home.vue')
},
't1': {
path: 't1',
name: 't1',
component: () => import('../views/T1.vue')
},
'password': {
path: 'password',
name: 'password',
component: () => import('../views/Password.vue')
},
'msg': {
path: 'msg',
name: 'msg',
component: () => import('../views/Msg.vue')
},
'userinfo': {
path: 'userinfo',
name: 'userinfo',
component: () => import('../views/UserInfo.vue')
}
} // 传入后台数据 生成路由表
menusToRoutes(menusData) // 将菜单信息转成对应的路由信息 动态添加
function menusToRoutes(data) {
const result = []
const children = [] result.push({
path: '/',
component: () => import('../components/Index.vue'),
children,
}) data.forEach(item => {
generateRoutes(children, item)
}) children.push({
path: 'error',
name: 'error',
component: () => import('../components/Error.vue')
}) // 最后添加404页面 否则会在登陆成功后跳到404页面
result.push(
{path: '*', redirect: '/error'},
) return result
} function generateRoutes(children, item) {
if (item.name) {
children.push(asyncRoutes[item.name])
} else if (item.children) {
item.children.forEach(e => {
generateRoutes(children, e)
})
}
}

所有的代码实现,我都放在 github 上,动态菜单的实现放在这个项目下的 src/components/Index.vuesrc/permission.js 和 src/utils/index.js

 

Vue页面权限控制和动态添加路由的更多相关文章

  1. vue动态添加路由,跳转页面时,页面报错路由重复:vue-router.esm.js?8c4f:16 [vue-router] Duplicate named routes definition: { name: "Login", path: "/login" }

    之前用了一个vue-element-admin做了一个小项目,里面用到了动态添加路由,动态展示侧边栏, 当我切换页面时,控制台总是警告提示路由重复,连续跳转几次页面后,控制台就被这些警告占满了, 于是 ...

  2. vue的动态路由(登录之后拿到动态路由通过addRouters()动态添加路由)

    登录后我们拿到路由动态路由,后端传的数据可能为这个 { path: '/index', meta: { title: '首页', icon: 'icon-shouye', tab_index: , / ...

  3. vue-element-admin登录逻辑,以及动态添加路由,显示侧边栏

    这段时间在研究element-admin,感觉这个库有许多值得学习的地方,我学习这个库的方法是,先看它的路由,顺着路由,摸清它的逻辑,有点像顺藤摸瓜. 这个库分的模块非常清晰,适合多人合作开发项目,但 ...

  4. SAAS云平台搭建札记: (三) AntDesign + .Net Core WebAPI权限控制、动态菜单的生成

    我们知道,当下最火的前端框架,非蚂蚁金服的AntDesign莫属,这个框架不仅在国内非常有名,在国外GitHub上React前端框架也排名第一.而且这个框架涵盖了React.Vue.Angular等多 ...

  5. vue-router 动态添加 路由

    动态添加路由可以用了做权限管理.登录后服务器端返回权限菜单,前端动态添加路由  然后在设置菜单 1.vue-router 有方法router.addRoutes(routes) 动态添加更多的路由规则 ...

  6. 【面试题】Vue2动态添加路由 router.addRoute()

    Vue2动态添加路由 点击打开视频讲解更加详细 场景: 一般结合VueX和localstorage一起使用 router.addRoutes vue-router4后 已废弃:使用 router.ad ...

  7. vue动态添加路由addRoutes之不能将动态路由存入缓存

    在我不知道vue的路由还可以通过addRoutes动态添加时,我只知道vue的路由都是写死在路由表中的,每当跳转时再去加载相应的路由.直到在一个新公司接到需要根据用户的权限显示不同的菜单的需求时才知道 ...

  8. Vue + Element UI 实现权限管理系统 前端篇(十三):页面权限控制

    权限控制方案 既然是后台权限管理系统,当然少不了权限控制啦,至于权限控制,前端方面当然就是对页面资源的访问和操作控制啦. 前端资源权限主要又分为两个部分,即导航菜单的查看权限和页面增删改操作按钮的操作 ...

  9. AntDesignPro的权限控制和动态路由

    最近看了AntDesignPro关于权限控制的官方文档以及自己框架里权限控制的实现,总结一下. 先贴一下官网上关于权限控制的图有利于理解 步骤如下: 判断是否有 AccessToken 如果没有则跳转 ...

随机推荐

  1. Thinkphp6源码分析之解析,Thinkphp6路由,Thinkphp6路由源码解析,Thinkphp6请求流程解析,Thinkphp6源码

    Thinkphp6源码解析之分析 路由篇-请求流程 0x00 前言: 第一次写这么长的博客,所以可能排版啊,分析啊,什么的可能会比较乱.但是我大致的流程已经觉得是说的够清楚了.几乎是每行源码上都有注释 ...

  2. 浏览器判断兼容IE

    很多时候IE浏览器的兼容性问题总是让人很头疼,或许是样式的或许是脚本的.总之因为IE的低版本问题会引发各种各样的问题出来. function isUnderIE10() {//IE 6,7,8,9 i ...

  3. C++实现双向循环链表

    本次博文是关于利用C++模板的方式实现的双向循环链表以及双向循环链表的基本操作,在之前的博文C++语言实现双向链表中,已经给大家分析了双向循环链表的结构,并以图示的方式给大家解释了双向循环链表的基本操 ...

  4. 一、华为模拟器eNSP下载与安装教程

    简单介绍一下 eNSP: eNSP是一款由华为提供的免费的图形化网络仿真工具平台,它将完美呈现真实设备实景(包括华为最新的ARG3路由器和X7系列的交换机),支持大型网络模拟,让你有机会在没有真实设备 ...

  5. spark本地开发环境搭建及打包配置

    在idea中新建工程 删除新项目的src,创建moudle 在父pom中添加spark和scala依赖,我们项目中用scala开发模型,建议scala,开发体验会更好(java.python也可以) ...

  6. 【three.js第四课】自定义材料、贴图。

    1.先去下载6张不同的图片素材放到项目中. 2.在[three.js第三课]的代码基础上添加自定义的材料 //自定义材料 cubeMaterial 数组 //map:用于加载图片,THREE.Text ...

  7. threejs创建地球

    上个月底,在朋友圈看到一个号称“这可能是地球上最美的h5”的分享,点进入后发现这个h5还很别致,思考了一会,决定要不高仿一个? 到今天为止,高仿基本完成, 线上地址 github地址 除了手机端的me ...

  8. 74HC595芯片的特性及使用方法和点评

    一 它能干什么?   74HC595是一个8位串行输入.平行输出的位移缓存器:平行输出为三态输出.在SCK的上升沿,单行数据由SDL输人到内部的8位位移缓存器,并由Q7‘输出,而平行输出则是在LCK的 ...

  9. G. 蚂蚁的镜像串

    单点时限: 1.0 sec 内存限制: 512 MB 一只聪明的蚂蚁在学习了回文串之后,一直觉得回文串不够优美,所以它决定自己定义一种新的字符串——镜像串 所谓镜像串,就是对一个字符串进行一整个完全的 ...

  10. codeforces 122C perfect team

    You may have already known that a standard ICPC team consists of exactly three members. The perfect ...