权限及动态路由

阅读: 9832    发布时间: 2018-09-04 11:12:39

一个后台重要的就是权限管理了,而要实现权限,无非是要达到这几点

  • 根据不同的权限,分配不同的后台菜单

  • 无权限的页面不能访问

  • 无权限的接口不能访问

1和3可以由后台轻松管理,而2则要麻烦一些,假如我们给所有页面都设置了路由,由于是单页面应用,用户访问某个页面,并不经过后台,所以用户可能会访问不属于自己权限的页面,因此我们想实现的功能是,根据用户的权限,加载相应的路由,即实现动态路由,这需要用到router.addRouters接口。

router.addRoutes

文档地址:https://router.vuejs.org/zh/api/#router-addroutes

router.addRoutes(routes: Array<RouteConfig>)

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


动态路由实现

路由设置

router文件夹下,我们设置两个文件,index.js和dynamic-router.js

index文件主要设置没有权限的路由,比如登录页面、404和403页面

import Vue from 'vue'
import Router from 'vue-router'

import Login from '@/pages/site/Login'
import NoFind from '@/pages/site/404'
import Forbidden from '@/pages/site/403'



Vue.use(Router)

export default new Router({
  mode: 'history',
  routes: [
    {
      path: '/site/login',
      name: 'login',
      component: Login,
      meta:{requiresAuth:false},
    },
    {
      path: '/404',
      name: '404',
      component:NoFind,
      meta:{requiresAuth:false},
    },
    {
      path: '/403',
      name: '403',
      component:Forbidden,
      meta:{requiresAuth:false},
    },


  ]
})

dynamic-router.js则设置我们需要动态分配的路由信息

/*
* 动态路由的配置表
* 用于获取权限后,生成对应的路由,然后动态添加
* 添加新页面后,到此处进行配置
*/
const routes=[
  {
    path: '/',
    name: 'dashboard',
    component: (resolve) => require(['@/pages/layout/Layout'], resolve),
    meta:{requiresAuth:true,noPermission:true},
  },
  {
    path: '/index',
    name: 'dashboard',
    component: (resolve) => require(['@/pages/layout/Layout'], resolve),
    meta:{requiresAuth:true,noPermission:true},
    children:[
      {
        path: '/site/update-pwd',
        name: 'site-update-pwd',
        component: (resolve) => require(['@/pages/site/UpdatePwd'], resolve),
        meta:{requiresAuth:false,noPermission:true},
      },
      {
        path: '/administrators/index',
        name: 'administrators-index',
        component: (resolve) => require(['@/pages/permission/AdministratorsIndex'], resolve),
        meta:{requiresAuth:true},
      },
      {
        path: '/administrators/edit',
        name: 'administrators-edit',
        component: (resolve) => require(['@/pages/permission/AdministratorsEdit'], resolve),
        meta:{requiresAuth:true},
      },
      {
        path: '/administrators/pwd',
        name: 'administrators-pwd',
        component: (resolve) => require(['@/pages/permission/AdministratorsPwd'], resolve),
        meta:{requiresAuth:true},
      },
      {
        path: '/roles/index',
        name: 'roles-index',
        component: (resolve) => require(['@/pages/permission/RolesIndex'], resolve),
        meta:{requiresAuth:true},
      },
      {
        path: '/roles/edit',
        name: 'roles-edit',
        component: (resolve) => require(['@/pages/permission/RolesEdit'], resolve),
        meta:{requiresAuth:true},
      },
      

      .......
      
    ]
  },
  
  //其他页面则都进入404
  {
    path: '*',
    redirect: '/404',
    meta:{requiresAuth:false,noPermission:true}
  }

]

//根据权限获取动态路由,如果子路由用户有权限,则肯定要给父路由的权限,通过递归的方式获取有权限的路由数组
function generateRouteByPermision(routes,permission) {

  let filter_result=[];
  for(let i=0;i<routes.length;i++){
    if(routes[i].children&&routes[i].children.length>0){
      let children_result=generateRouteByPermision(routes[i].children,permission)
      if(children_result.length>0){
        routes[i].children = children_result
        filter_result.push(routes[i])
      }else {
        routes[i].children = []
        if(routes[i].meta.noPermission||permission.indexOf(routes[i].path)>-1){
          filter_result.push(routes[i])
        }
      }
    }else{
      if(routes[i].meta.noPermission||permission.indexOf(routes[i].path)>-1){
        filter_result.push(routes[i])
      }
    }
  }

  return filter_result
}

export default {
  routes: routes,
  generateRouteByPermision:generateRouteByPermision
}


在main.js中,通过路由前置守卫,获取权限并动态添加路由

main.js

// The Vue build version to load with the `import` command
// (runtime-only or standalone) has been set in webpack.base.conf with an alias.
import Vue from 'vue'
import App from './App'
import router from './router/index'
import dynamicRouter from './router/dynamic-router'
import store from './store/index'
import authorize from './utils/base/authorize'
import netwrok from './utils/base/network'
import config from './utils/config/config'
import api from './utils/config/api'
import toastRegistry from './components/plugins/toast/index'
import confirmRegistry from './components/plugins/confirm/index'



// 这里也可以直接执行 toastRegistry()
Vue.use(toastRegistry)
Vue.use(confirmRegistry)


router.beforeEach(async (to,from,next)=>{

  if(to.meta.requiresAuth===false){
    //不需要登录的直接放行
    next()
  }else if(!authorize.checkLogin()){
    //如果页面需要登录,且登录失效,进入登录页面
    next({
      path:config.login_path,
      query: { redirect: to.fullPath }
    })
  }else {
    //已经登录
    //是否已经拉取menu,权限等信息
    if(!store.state.menu_loaded){
      //如果页面还没有拉取menu
      await netwrok.post(api.get_user_info,'',true).then((res)=>{
        store.commit('SET_USER_INFO',res)
        
        //获取动态路由
        let dy_routers=dynamicRouter.generateRouteByPermision(dynamicRouter.routes,res.permission);
        //动态添加路由
        router.addRoutes(dy_routers)

      })
      next({ ...to, replace: true })

    }else{
      next()
    }

  }

})

/* eslint-disable no-new */
new Vue({
  el: '#app',
  router,
  store,
  components: { App },
  template: '<App/>'
})


-END-