vue前端权限控制

我司开发一套系统,需要做权限管理,不同角色的用户权限不一样,登录系统看到的东西是不一样的,而且调用接口、登陆是否有效都需要通过一个身份认证token来确认。经过商量,我们做的思路如下:

1、用户先登陆,拿到认证的token,然后存到localStorage中,代码如下:

 1 getInfo.post('api-token-auth/',{username:_self.loginData.userCount,password:_self.loginData.password}).then(function(data){
 2                             if(data.data.code == 0){
 3                                 let jwtSession = 'JWT'+' '+data.data.token;
 4                                 localStorage.setItem("checkSession", jwtSession);
 5                                 localStorage.setItem("userInfo", data.data.userinfo.username);
 6                                 localStorage.setItem("routes",JSON.stringify(data.data.userinfo.permissions))
 7                                 // 路由权限过滤
 8                                 var menuData = JSON.parse(localStorage.getItem('routes'));
 9                                 var localRouter = _self.$router.options.routes
10                                 for(let i = 0;i<menuData.length;i++){
11                                   for(let q = 0;q<localRouter.length;q++){
12                                     if(menuData[i].codename == localRouter[q].path.replace(/\//,"")){
13                                       localRouter[q].hidden = false;
14                                     } 
15                                   }
16                                 }
17                                 _self.$router.addRoutes(localRouter)
18                                 _self.$router.push({ path: '/ops_menu_sever_manage'});
19                             }
20                             else{
21                                 _self.$message({
22                                     message: data.data.msg,
23                                     type: 'warning'
24                                 });
25                                 // _self.$router.push({ path: '/login'});
26                             }
27                             
28                        });

2、我们异步请求用的是axios,所以在配置axios的时候添加了请求拦截器,每次请求的时候,在localStorage中获取我们存的token,并且给请求头部添加一个Authorization请求头,代码如下:

 1 // CMDB借口实例
 2 export const cmdbAjax = axios.create({
 3     baseURL:cmdbUrl,
 4     timeout:10000
 5 })
 6 cmdbAjax.interceptors.request.use(function (config) {
 7     config.headers.common['Authorization'] = localStorage.getItem('checkSession');
 8     return config;
 9   }, function (error) {
10     return Promise.reject(error);
11   });

3、登陆成功,后台会把当前用户所需要的权限全返回给我,拿到之后,也一并存到localStorage里面;

 1 localStorage.setItem("routes",JSON.stringify(data.data.userinfo.permissions)) 

4、开发系统的时候我们正常在本地配好路由,路由表如下:

import Vue from 'vue'
import Router from 'vue-router'
import layout from '@/views/layout/layout'
import devicemanage from '@/views/devicemanage/devicemanage'
import devicecontrol from '@/views/devicecontrol/devicecontrol'
import deviceadd from '@/views/deviceadd/deviceadd'
import deviceupdate from '@/views/deviceupdate/deviceupdate'
import login from '@/views/login/login'

Vue.use(Router)

 const router = new Router({
  routes: [
      {
          path:'/',
          component:login,
      },
      {
          path:'/login',
          component:login,
      },
      {
          path: '/deviceadd',
          component: layout,
          hidden:true,
          children: [
              {
                  path: '/deviceadd',
                  component:deviceadd,
                  name: 'deviceadd',
              }
          ]
      },
      {
          path: '/deviceupdate',
          component: layout,
          hidden:true,
          children: [
              {
                  path: '/deviceupdate',
                  component:deviceupdate,
                  name: 'deviceupdate',
              }
          ]
      },
      {
          path: '/ops_menu_sever_manage',
          component: layout,
          hidden:true,
          children: [
              {
                  path: '/devicemanage',
                  component:devicemanage,
                  name: 'devicemanage',
                  meta: { title: '设备管理', icon: 'yingyong'  },
              }
          ]
      },
      {
          path: '/devicecontrol',
          component: layout,
          hidden:true,
          children: [
              {
                  path: 'devicecontrol',
                  component:devicecontrol,
                  meta: { title: '设备监控', icon: 'shezhi'  },
              },
          ]
      },
      {
          path: '/ops_menu_analytical_manage',
          component: layout,
          hidden:true,
          children: [
              {
                  path: 'devicecontrol',
                  component:devicecontrol,
                  meta: { title: '解析管理', icon: 'jiexi'  },
              },
          ]
      },

      {
          path: '/ops_menu_basic_manage',
          component: layout,
          hidden:true,
          children: [
              {
                  path: 'devicecontrol',
                  component:devicecontrol,
                  meta: { title: '基础运维', icon: 'yunwei1'  },
              },
          ]
      },

      {
          path: '/ops_menu_channel_manage',
          component: layout,
          hidden:true,
          children: [
              {
                  path: 'devicecontrol',
                  component:devicecontrol,
                  meta: { title: '频道管理', icon: 'fm'  },
              },
          ]
      },
      {
          path: '/ops_menu_issued_manage',
          component: layout,
          hidden:true,
          children: [
              {
                  path: 'devicecontrol',
                  component:devicecontrol,
                  meta: { title: '下发管理', icon: 'xiafa'  },
              },
          ]
      },
      {
          path: '/ops_menu_log_manage',
          component: layout,
          hidden:true,
          children: [
              {
                  path: 'devicecontrol',
                  component:devicecontrol,
                  meta: { title: '日志管理', icon: 'rizhi'  },
              },
          ]
      },
      {
          path: '/ops_menu_monitor_manage',
          component: layout,
          hidden:true,
          children: [
              {
                  path: 'devicecontrol',
                  component:devicecontrol,
                  meta: { title: '监控管理', icon: 'jiankong'  },
              },
          ]
      },
      {
          path: '/ops_menu_order_manage',
          component: layout,
          hidden:true,
          children: [
              {
                  path: 'devicecontrol',
                  component:devicecontrol,
                  meta: { title: '工单系统', icon: 'gongdan'  },
              },
          ]
      },
      {
          path: '/ops_menu_user_manage',
          component: layout,
          hidden:true,
          children: [
              {
                  path: 'devicecontrol',
                  component:devicecontrol,
                  meta: { title: '用户管理', icon: 'yonghu2'  },
              },
          ]
      },
  ]
})


export default router

4、此时我们获取了后台返回的权限数据,通过this.$router.options.routes获取vue实例中挂在的我们配置好的路由表,循环遍历着两个数组,如果后台返回有权限,那么久吧vue实例中的路由表的hidden属性改为false。

此时已经感觉大功告成,赶紧去页面登录账号试一试。感觉还真行。然后就手贱刷新一把。完了,菜单栏啥也没有了。

我百思不得其解,后来 就赶紧找我的小伙伴商量,找出问题所在了。(在这里要特别感谢我的同事展展给予的无私帮助)

原来特码的,刷新页面之后,vue实例重新创建,路由也会重新加载一遍(也就是把我们配置好的路由表重新挂到了vue实例中),那么我们修改的路由就会消失。此时我已经为自己的无知付出惨痛的时间成本代价。尽然知道问题所在,那么就好解决了,我就赶紧机智的在main.js中添加如下代码:

 1    // 路由权限过滤
 2 if(localStorage.getItem("checkSession")){
 3     var menuData = JSON.parse(localStorage.getItem('routes'));
 4     var localRouter = router.options.routes
 5     for(let i = 0;i<menuData.length;i++){
 6       for(let q = 0;q<localRouter.length;q++){
 7         if(menuData[i].codename == localRouter[q].path.replace(/\//,"")){
 8           localRouter[q].hidden = false;
 9         } 
10       }
11     }
12     router.addRoutes(localRouter)
13 }

赶紧再去重新页面登录一次,发现完美解决问题。再怎么刷新都不会消失了。开心,为自己撒花。然后同事也手贱,特么竟然换了一个不同权限的账号登陆,发现登陆之后的菜单栏竟然和之前登陆的账号完全一样。没有的权限也能看见了,除非刷新一下页面。看见没,重点就在“刷新一下页面”就没事了。此时犯的错误还是和刚才那个是一样的,需要重新创建一下vue实例然后重新挂在一次路由就好了。赶紧去退出登录的时候添加刷新页面代码:

1 loginOut(){
2                 localStorage.removeItem('checkSession');
3                 localStorage.clear();
4                 this.$router.push({path:'/login'});
5                 window.location.reload()
6             }

此时,再去测,完美。

对于vue我也是新手,还有好多地方理解的不到位,希望对阅读本文的人有素帮助,vue大佬们也欢迎尽情吐槽,碰撞才会促进进步。

猜你喜欢

转载自www.cnblogs.com/zhanghanghang/p/9487571.html