vue后台管理系统之权限管理

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/oncemore520/article/details/82419711

最近在做一个基于vue+elementUI+es6的后台管理系统,权限管理这块是非常重要的,这块是前台来做的。

  • 配置动态路由和静态路由
  • 通过后台传过来的isAdmin来判断是管理员权限还是非管理员权限
  • 管理员权限就不用递归遍历路由,直接开放所有权限,否则就要递归遍历路由
  • *对于三级路由的处理
  • 对于白名单的处理
  • 创建新用户,权限的保存

配置动态路由和静态路由

对于那些始终要开放的权限,放在静态路由里。比如登录啊,密码的修改等等
这里写图片描述
这里写图片描述

通过后台传过来的isAdmin来判断是管理员权限还是非管理员权限

全局守卫
你可以使用 router.beforeEach 注册一个全局前置守卫:
const router = new VueRouter({ … })
router.beforeEach((to, from, next) => {
// …
})
当一个导航触发时,全局前置守卫按照创建顺序调用。守卫是异步解析执行,此时导航在所有守卫 resolve 完之前一直处于 等待中。
每个守卫方法接收三个参数:
to: Route: 即将要进入的目标 路由对象
from: Route: 当前导航正要离开的路由
next: Function: 一定要调用该方法来 resolve 这个钩子。执行效果依赖 next 方法的调用参数。

const whiteList = ['/login','/password']// no redirect whitelist

router.beforeEach((to, from, next) => {
  NProgress.start() // start progress bar
  if (getToken()) { // determine if there has token
    /* has token*/
    if (to.path === '/login') {
      next({ path: '/' })
      NProgress.done()
    } else {
      if (store.getters.name.length === 0) { // 判断当前用户是否已拉取完user_info信息
        store.dispatch('GetUserInfo').then(res => { // 拉取user_info          
          /** 
           * note: roles must be a array! such as: 
           * [
           *  {
           *    name:'pageview',
           *    services:['/user/info','/user/list'],
           *    children:[
           *      {
           *        name:'pageview',
           *        services:['/user/info','/user/list'],
           *      }
           *    ]
           *  }
           * ]
           * */
          const roles = res.data.roles
          const isAdmin = res.data.isAdmin
          store.dispatch('GenerateRoutes', { isAdmin, roles }).then(() => { // 根据roles权限生成可访问的路由表
            router.addRoutes(store.getters.addRouters) // 动态添加可访问路由表
            console.dir(store.getters.addRouters)
            next({ ...to, replace: true }) // hack方法 确保addRoutes已完成 ,set the replace: true so the navigation will not leave a history record
          })
        }).catch(() => {
          store.dispatch('FedLogOut').then(() => {
            Message.error('Verification failed, please login again')
            next({ path: '/login' })
          })
        })
      } else {
        next()
      }
    }
  } else {
    /* has no token*/
    if (whiteList.indexOf(to.path) !== -1) { // 在免登录白名单,直接进入
      next()
    } else {
      next('/login') // 否则全部重定向到登录页
      NProgress.done() // if current page is login will not trigger afterEach hook, so manually handle it
    }
  }
})

router.afterEach(() => {
  NProgress.done() // finish progress bar
})

这里边设置login登录和password密码修改为白名单,可以直接免登陆,进入白名单,根据后台传过来的roles生成可进行访问的路由表

import { asyncRouterMap, constantRouterMap } from '@/router'

/**
 * 通过meta.role判断是否与当前用户权限匹配
 * @param roles
 * @param route
 */
function hasPermission(roles, route) {
  const checker = roles.filter(role => {
    if (route.name === role.name || route.threechil == true) {
      return true
    } else {
      if (role.children && role.children.length > 0) {
        return hasPermission(role.children, route)
      }
    }
  })
  return checker.length
}

/**
 * 递归过滤异步路由表,返回符合用户角色权限的路由表
 * @param asyncRouterMap
 * @param roles
 */
function filterAsyncRouter(asyncRouterMap, roles) {
  const accessedRouters = asyncRouterMap.filter(route => {
    if (hasPermission(roles, route)) {      
      if (route.children && route.children.length) {
        route.children = filterAsyncRouter(route.children, roles)
      }
      return true
    }
    return false
  })
  return accessedRouters
}

const permission = {
  state: {
    asyncRouters: JSON.parse(JSON.stringify(asyncRouterMap)),
    routers: constantRouterMap,
    addRouters: [],
  },
  mutations: {
    SET_ROUTERS: (state, routers) => {
      state.addRouters = routers
      state.routers = constantRouterMap.concat(routers)
    }
  },
  actions: {
    GenerateRoutes({ commit }, data) {
      return new Promise(resolve => {
        const { isAdmin, roles } = data
        let accessedRouters
        if (isAdmin == '1') {

          accessedRouters = asyncRouterMap
        }else if(isAdmin == '0') {
          accessedRouters = filterAsyncRouter(asyncRouterMap, roles)
          accessedRouters.push(asyncRouterMap[asyncRouterMap.length - 1]);
        }
        commit('SET_ROUTERS', accessedRouters)
        resolve()
      })
    }
  }
}

export default permission

这里边便是进行前台权限控制的路由代码,这里为什么要有route.threechil == true就开放权限呢,是因为遇到了一个bug
之前一直用管理员账号测试的代码,所以在文章管理里边有一个添加,修改功能,之前是直接把这两个功能的页面作为二级路由和文章管理首页同级,大概是这样的页面:
这里写图片描述
编辑和新增是一个新页面,但是又不能再侧边栏里边出现,在路由中有一个属性是hidden:true设置之后就不会再侧边栏出现了,但是呢,有个问题就是我做权限保存的时候并不会保存这个页面路由给后台,自然后台也就不会给我传过来,所以我不是管理员权限的时候递归的时候就不会递归到这个页面了,自然404就出现了!所以需要设置三级路由嵌套
这里写图片描述
要注重二级路由和一级路由里引入的组件component,一级路由引入的组件时layout组件,封装的一个整体侧边栏和上边的标签,而二级路由layer只是一个简单的《rouer-view》,给三级路由都加上threechil:true就是在递归的时候遇到这个属性,就开放权限。
还有一个情况就是,侧边栏最多出现两极,三级菜单是不显示的。
这里写图片描述
这样的话就需要改一改侧边栏里边遍历的代码了
这里写图片描述

末尾

写的稍微有点乱,希望能看懂,哈哈

猜你喜欢

转载自blog.csdn.net/oncemore520/article/details/82419711