vue路由权限校验

标签: vue 路由 | 发表时间:2020-06-06 15:33 | 作者:阿婧
出处:https://juejin.im/welcome/frontend

引言

做后台系统的时候,难免会有用户权限的判断。admin可以查看全部菜单,user只能查看部分菜单。

一开始接触这个需求的时候,完全是纯前端做的。在配置路由的时候,加一个roles的属性,通过判断用户的roles是否与路由的roles属性相匹配来作为显示隐藏的依据

   {
  path: '/router',
  name: 'router',
  meta: {
    title: '标题',
    roles: ['admin','user']
  },
  component: index,
  children: [
    {
      path: 'children',
      name: 'children',
      meta: {
        title: '子标题',
        roles: ['admin','user']
      },
      component: child
    }
  ]
}
复制代码
  // 过滤路由 menuList-菜单 roles-用户角色
const checkMenuList = (menuList, roles) => {
  for (let i = 0; i < menuList.length; i++) {
    if (!compareEqual(roles, menuList[i].meta.roles) || menuList[i].meta.noRenderTree) {
      menuList.splice(i, 1)
      i -= 1
    } else {
      if (menuList[i].children) {
        checkMenuList(menuList[i].children, roles)
      }
    }
  }
  return menuList
}
复制代码

这样做确实可以实现给不同用户展示不同的菜单。但是如果用户权限发生改变,前端就需要发版。本着万物皆可灵活配置的原则。

需求

首先我们要了解,我们要做什么。

我们希望我们可以通过用户权限配置功能,达到灵活配置路由权限,由服务器端返回需要展示的路由权限,前端做展示。

思路

  1. 前端配置好项目全部页面的路由
  2. 服务器端返回该用户的权限列表,前端去匹配,最后返回一个路由列表,作为菜单
  3. 为了更好的用户体验,当用户输入异常的路由时,我们要重定向到一个404页面,提示用户该页面不存在。
  4. 基于第3点,我们在每次跳转的时候,还需要判断这个页面是否存在,该用户是否有权限进行跳转

实现

ok 思路整理完了。现在就开始来实现吧!

首先,routers是需要在前端注册,我们要先配置整个页面的routers。

除了系统的菜单之外,我们还需要配置403错误页面,还有login、首页这些基本路由。由于系统菜单还需要与服务器端返回的路由列表进行匹配,暂时不进行注册

  // router.js

 // 基本路由
export const defaultRouter = [
  { path: '/', component: index }, // 首页
  { path: '/login', name: 'login', component: login } // 登录页
 ]
 
 // 项目全部页面
export const appRouter = [
   {
    path: '/router1',
    name: 'router1',
    redirect: '/router1/test1',
    component: router1,
    meta: { title: '路由1'},
    children: [
      { path: 'test1', name: 'test1', component: test1, meta: { title: '测试1' } },
      { path: 'test2', name: 'test2', component: test1, meta: { title: '测试2' } }
    ]
  },
 ]
 // 这个是我们页面初始化时候,注册的routes
const routers = [ 
  ...defaultRouter
]
const RouterConfig = {
  routes: routers
}
const router = new VueRouter(RouterConfig)
复制代码

全部路由都注册完了,接下来就要匹配用户可访问的路由了,这一步需要和服务器端一起约定规则。

  // 服务器端返回的键值对:  路由名:是否有权限
authRouter:{
    'test1': false,
    'test2': true
}
复制代码

拿到服务器端返回的用户权限之后,就开始过滤路由

  // 过滤路由 appRouterCopy-项目全部页面 authRouter-权限列表
const checkMenuList = (appRouterCopy, authRouter) => {
    for (let i = 0; i < appRouterCopy.length; i++) {
        let {name, children} = appRouterCopy[i]
        if (authRouter[name] === false) {
            appRouterCopy.splice(i, 1)
            i--
        } else if (children && children.length) {
            checkMenuList(children, authRouter)
        }
    }
}
复制代码

得到过滤后的路由之后,使用 addRoutes进行注册。注意404路由配置要在最后加上。

  let error404Page = { path: '/*', name: 'error-404', meta: { title: '404-页面不存在'}, component: error404Page}
router.addRoutes([...appRouterCopy, error404Page])
复制代码

到此我们就得到了用户有权限的页面了,可以把得到的列表作为系统菜单渲染上去。接下来就要处理一下跳转异常的状况了。需要用到 beforeEach对每次跳转进行拦截判断

  router.beforeEach(((to, from, next) => {
    if (isNotLog && to.name !== 'login') {
        // 未登录 跳转到登录页
         next({ name: 'login' })
    } else if (to.name && (to.name === 'login' || to.name.indexOf('error') !== -1)){
        // 跳转异常
        next()
    } else {
        // 校验用户权限
        checkUser(next, to ,router)
    }
})

const checkUser = async (next, to ,router) => {
    if (isNotUser) {
        // 首次登陆系统,没有用户信息的时候 需要获取用户信息做过滤路由的操作
        const authRouter = getAuthRouter() // 获取用户权限
        checkMenuList(appRouterCopy, authRouter)
        const error404Page = { path: '/*', name: 'error-404', meta: { title: '404-页面不存在'}, component: error404Page}
        router.addRoutes([...appRouterCopy, error404Page])
        if (!appRouterCopy.length) {
            // 用户没有有权限的路由 可以跳转到404或者登录页
            next({ ...error404Page, replace: true })
        } else {
            next({ ...to, replace: true })
        }
    } else {
        next()
    }
}
复制代码

相关 [vue 路由] 推荐:

vue路由权限校验

- - 掘金前端
做后台系统的时候,难免会有用户权限的判断. admin可以查看全部菜单,user只能查看部分菜单. 一开始接触这个需求的时候,完全是纯前端做的. 在配置路由的时候,加一个roles的属性,通过判断用户的roles是否与路由的roles属性相匹配来作为显示隐藏的依据. // 过滤路由 menuList-菜单 roles-用户角色 const checkMenuList = (menuList, roles) => { for (let i = 0; i < menuList.length; i++) {.

vue-router+vuex实现加载动态路由和菜单-爱咖啡-51CTO博客

- -
动态路由加载和动态菜单渲染的应用在后端权限控制中十分常见,后端只要加载权限路由进行渲染返回到浏览器就可以. 在前后端分离中,权限控制动态路由和动态菜单也是一个非常常见的问题. 其实我们最最理想的效果是什么呢. 我们访问一个应用,在登录之前有哪些路由是一定要加载的呢. 你看我总结如下,你看下是不是这些:.

ssr vuejs/vue-hackernews-2.0: HackerNews clone built with Vue 2.0, vue-router & vuex, with server-side rendering

- -
This is a demo primarily aimed at explaining how to build a server-side rendered Vue app, as a companion to our SSR documentation. #install dependenciesnpm install#or yarn#serve in dev mode, with hot reload at localhost:8080npm run dev#build for productionnpm run build#serve in production modenpm start.

Vue 移动端框架

- - IT瘾-jianshu
vonic 一个基于 vue.js 和 ionic 样式的 UI 框架,用于快速构建移动端单页应用,很简约. 中文文档| github地址| 在线预览. vux 基于WeUI和Vue(2.x)开发的移动端UI组件库. 基于webpack+vue-loader+vux可以快速开发移动端页面,配合vux-loader方便你在WeUI的基础上定制需要的样式.

微豆 - Vue 2.0 实现豆瓣 Web App 教程

- - SegmentFault 最新的文章
一个使用 Vue.js 与 Material Design 重构 豆瓣 的项目. 项目网站 http://vdo.ralfz.com/. # 克隆项目到本地 git clone https://github.com/RalfZhang/Vdo.git # 安装依赖 npm install # 在 localhost:8080 启动项目 npm run dev.

浅谈Vue组件在实际项目中的应用

- - JDC | 京东设计中心
Vue.js 是一套构建用户界面的渐进式框架,目标是通过尽可能简单的 API 实现响应的数据绑定和组合的视图组件. 虽然目前 Vue 已经很火了,但不可否认的是,仍有很多人刚刚开始学习使用 Vue 来构建前端项目,从生疏的初学者到熟练运用 Vue 的过程中,不可避免地会走一些弯路. 为了实现某个功能,也许尝试过很多方法,最终蓦然回首,才发现当初犯下的错误是那么幼稚.

vue快速入门的三个小实例

- - SegmentFault 最新的文章
用vue做项目也有一段时间了,之前也是写过关于vue和webpack构建项目的相关文章,大家有兴趣可以去看下 webpack+vue项目实战(一,搭建运行环境和相关配置)(这个系列一共有5篇文章,这是第一篇,其它几篇文章链接就不贴了). 但是关于vue入门基础的文章,我还没有写过,那么今天就写vue入门的三个小实例,这三个小实例是我刚接触vue的时候的练手作品,难度从很简单到简单,都是入门级的.

vue父子组件通信高级用法

- - SegmentFault 最新的文章
vue项目的一大亮点就是组件化. 使用组件可以极大地提高项目中代码的复用率,减少代码量. 但是使用组件最大的难点就是父子组件之间的通信. . . // 参数就是子组件传递出来的数据.

Vue 组件数据通信方案总结

- - IT瘾-dev
(给前端大全加星标,提升前端技能). 作者:政采云前端团队 公号 / 季节 (本文来自作者投稿). 初识 Vue.js ,了解到组件是 Vue 的主要构成部分,但组件内部的作用域是相对独立的部分,组件之间的关系一般如下图:. 组件 A 与组件 B 、C 之间是父子组件,组件 B 、C 之间是兄弟组件,而组件 A 、D 之间是隔代的关系.

vue 文件多了, webpack 热加载很慢? - V2EX

- -
点我最近刚好在看 webpack,如果楼主时间多可以去我博客看一下 webpack 相关的三篇文章,不要脸的放一下博客. 如果时间不够只是想解决这个问题,那么我尝试正儿八经回答一下. 1.把 webpack 升级到 4.0. 3.使用 DLLplugin,happypack 等构建加速插件. 4.检查 loader/eslint 是否配置错误 /不合理.