Permissions vue how to achieve back office systems of control

I. Introduction

In advertising the project, the role of rights management card is a difficulty quite a long time. First, we determine the access control divided into two parts, which according to a finer grain size of points:

  • Interface to access control permissions
  • Control permissions page

    • Whether the menu page can be accessed
    • Button page (add, delete, change) access control whether

Here we look at is how to achieve these two access control.

Second, the interface access control permissions

Interface is check the user's permission. Normally, when a user logs on to the reception server needs to return a Token, and then later when you need to call the front desk every time interfaces to bring this Token,

Then the server after obtaining the Token for comparison, if you can access through.

The conventional approach is successful login in the background in the callback returned directly to the Token storage sessionStorag​e, then when a request to the Token headers passed out into the background, as follows:

this.$http({
          method: 'get',
          url: 'test/query?id=20',
          withCredentials: true,
          headers: {
            token: sessionStorage.getItem('token'),
            name: sessionStorage.getItem('name')    //应后台需求传的用户名
          }
        }).then(response => {
          //请求成功后的操作
        })

Later found in some articles axios Token can be directly inserted into the interceptor config.headers.Authorization, as the global passed. Here is the code section:

//main.js
import axios from 'axios'

// 实例化Axios,并进行超时设置
const service = axios.create({
    timeout: 5000
})
// baseURL
// axios.defaults.baseURL = 'https://api.github.com';

// http request 拦截器
// 每次请求都为http头增加Authorization字段,其内容为token
service.interceptors.request.use(
    config => {
        if (store.state.user.token) {
            config.headers.Authorization = `token ${store.state.user.token}`;
        }
        return config
    },
    err => {
        return Promise.reject(err)
    }
);
export default service

Third, access control page

Have already said, access control page is divided into two:

  • Whether the menu page can be accessed
  • Button page (add, delete, change) access control whether

These rights are generally carried out in a fixed configuration page, after saving the record to the database.


Button authority aside, page access in the implementation can be divided into two ways:

  • Show all menu, when the user accesses the menu is not within their authority, suggesting insufficient permissions
  • Show only within the limits of the current user can access the menu, if the user mandatory access through URL, will go directly to 404

Since I can not point to show up after that count several meanings, make me play it? The so-called sight of the net, after comprehensive consideration, certainly more in line with program two good user experience.

Well, we now sort out what the approximate page access process:

Process rights

After the completion of the process of combing We started to write in detail.

1, create a routing table

Create a routing table is actually not difficult, according vue-router official documentation examples to write directly on the line. But because some page does not require access,

So you need to log in, 404, maintenance and other pages written default route, while other pages need written permission to a variable or a file, which can

In order to effectively reduce ongoing maintenance pressure.

Paste the following code index.js, asynchronous routing will reduce the amount, so as not to occupy too much space.

// router/index.js
import Vue from 'vue'
import Router from 'vue-router'
import App from '@/App'
import store from '../store/index'

Vue.use(Router);

//手动跳转的页面白名单
const whiteList = [
  '/'
];
//默认不需要权限的页面
const constantRouterMap = [
  {
    path: '/',
    name: '登录',
    component: (resolve) => require(['@/components/login'], resolve)
  },
  {
    path: '/index',
    name: 'nav.Home',
    component: (resolve) => require(['@/components/index'], resolve)
  },
  {
    path: '/templateMake',
    name: '模板制作',
    component: (resolve) => require(['@/components/Template/templateMake'], resolve)
  },
  {
    path: '/programMack',
    name: '节目制作',
    component: (resolve) => require(['@/components/Template/programMack'], resolve)
  },
  {
    path: '/release',
    name: '节目发布',
    component: (resolve) => require(['@/components/Program/release'], resolve)
  }
]

//注册路由
export const router = new Router({
  routes: constantRouterMap
});

//异步路由(需要权限的页面)
export const asyncRouterMap = [

  {
    path: '/resource',
    name: 'nav.Resource',
    meta: {
      permission: []
    },
    component: (resolve) => require(['@/components/Resource/resource'], resolve)
  },
  {
    path: '/template',
    name: 'nav.Template',
    meta: {
      permission: []
    },
    component: (resolve) => require(['@/components/Template/template'], resolve)
  },
  {
    path: '/generalSet',
    name: 'nav.System',
    meta: {
      permission: []
    },
    component: (resolve) => require(['@/components/SystemSet/generalSet'], resolve)
  },
  {
    path: '',
    name: 'nav.Log',
    component: App,
    children: [
      {
        path: '/userLog',
        name: 'nav.UserLog',
        meta: {
          permission: []
        },
        component: (resolve) => require(['@/components/Log/userLog'], resolve),
      },
      {
        path: '/operatingLog',
        name: 'nav.SystemLog',
        meta: {
          permission: []
        },
        component: (resolve) => require(['@/components/Log/operatingLog'], resolve),
      },
    ]
  }
  ]
];

Note: There is a very local needs attention is the 404 page must be loaded last, if put together constantRouterMap declared 404 behind the so pages are intercepted 404 detailed questions, see addRoutes when you've got a wildcard route for 404s does not work

2, page access

At the beginning we sort out a general page access process. Let us first implement the core components:

Access Process

We first get the user permissions list, where we will be exposed to vuex state management, official documents are detailed, described here is not too much, please see the code below:

// store/index.js
import Axios from 'axios'
import Vue from 'vue'
import Vuex from 'vuex'

Vue.use(Vuex);
const axios = Axios.create();

const state = {
  mode: 'login',
  list: []
};

const getters = {};

const mutations = {
  setMode: (state, data) => {
    state.mode = data
  },
  setList: (state, data) => {
    state.list = data
  }
};

const actions = {
  // 获取权限列表
  getPermission({commit}) {
    return new Promise((resolve, reject) => {
      axios({
        url: '/privilege/queryPrivilege?id=' + sessionStorage.getItem('privId'),
        methods: 'get',
        headers: {
          token: sessionStorage.getItem('token'),
          name: sessionStorage.getItem('name')
        }
      }).then((res) => {
        // 存储权限列表
        commit('setList', res.data.cust.privileges[0].children);
        resolve(res.data.cust.privileges[0].children)
      }).catch(() => {
        reject()
      })
    })
  }
};

export default new Vuex.Store({
  state,
  mutations,
  actions,
  getters
})

Well, we now request back to get the right data, to store the data to the vuex the following, we need to use to write before returning the data to match the asynchronous routing table, the matching results and static routing tables combine, open into the final actual routing table .

One of the most critical is the use of a addRoutes method vue-router2.2.0 new version added, we look at how the official document to explain this method:

router.addRoutes (routes) 2.2.0+ 
dynamically add more routing rules. Parameters must be an array of routes in line with the requirements of the option.

That we can now start using addRoutes route matches. Look at the code below:

// router/index.js
/**
 * 根据权限匹配路由
 * @param {array} permission 权限列表(菜单列表)
 * @param {array} asyncRouter 异步路由对象
 */
function routerMatch(permission, asyncRouter) {
  return new Promise((resolve) => {
    const routers = [];
    // 创建路由
    function createRouter(permission) {
         // 根据路径匹配到的router对象添加到routers中即可
      permission.forEach((item) => {
        if (item.children && item.children.length) {
          createRouter(item.children)
        }
        let path = item.path;
        // 循环异步路由,将符合权限列表的路由加入到routers中
        asyncRouter.find((s) => {
          if (s.path === '') {
            s.children.find((y) => {
              if (y.path === path) {
                y.meta.permission = item.permission;
                routers.push(s);
              }
            })
          }
          if (s.path === path) {
            s.meta.permission = item.permission;
            routers.push(s);
          }
        })
      })
    }

    createRouter(permission)
    resolve([routers])
  })
}

Then we write navigate hook

// router/index.js
router.beforeEach((to, form, next) => {
  if (sessionStorage.getItem('token')) {
    if (to.path === '/') {
      router.replace('/index')
    } else {
      console.log(store.state.list.length);
      if (store.state.list.length === 0) {
          //如果没有权限列表,将重新向后台请求一次
        store.dispatch('getPermission').then(res => {
            //调用权限匹配的方法
          routerMatch(res, asyncRouterMap).then(res => {
              //将匹配出来的权限列表进行addRoutes
            router.addRoutes(res[0]);
            next(to.path)
          })
        }).catch(() => {
          router.replace('/')
        })
      } else {
        if (to.matched.length) {
          next()
        } else {
          router.replace('/')
        }
      }
    }
  } else {
    if (whiteList.indexOf(to.path) >= 0) {
      next()
    } else {
      router.replace('/')
    }
  }
});

Here we have completed the access control of the pages visited, then we have to explain the rights of part of the operation button.

Fourth, the operating authority data

Do you remember our previous routing configurations extra code, let's look out:

//异步路由(需要权限的页面)
export const asyncRouterMap = [

  {
    path: '/resource',
    name: 'nav.Resource',
    meta: {
      permission: []
    },
    component: (resolve) => require(['@/components/Resource/resource'], resolve)
  },
  {
    path: '/template',
    name: 'nav.Template',
    meta: {
      permission: []
    },
    component: (resolve) => require(['@/components/Template/template'], resolve)
  },
  {
    path: '/generalSet',
    name: 'nav.System',
    meta: {
      permission: []
    },
    component: (resolve) => require(['@/components/SystemSet/generalSet'], resolve)
  },
  {
    path: '',
    name: 'nav.Log',
    component: App,
    children: [
      {
        path: '/userLog',
        name: 'nav.UserLog',
        meta: {
          permission: []
        },
        component: (resolve) => require(['@/components/Log/userLog'], resolve),
      },
      {
        path: '/operatingLog',
        name: 'nav.SystemLog',
        meta: {
          permission: []
        },
        component: (resolve) => require(['@/components/Log/operatingLog'], resolve),
      },
    ]
  }
  ]
];

Increase meta fields for each route page. RouterMatch matching function in the permissions field assignment to detail here. This will get this field in route objects for each page.

asyncRouter.find((s) => {
          if (s.path === '') {
            s.children.find((y) => {
              if (y.path === path) {
                  //赋值
                y.meta.permission = item.permission;
                routers.push(s);
              }
            })
          }
          if (s.path === path) {
            s.meta.permission = item.permission;
            routers.push(s);
          }
        })

Next we write the elements of a vue custom instruction page requires authentication to judge, for example, like this:

<a @click="upload" v-allow="'3'"></a> /* 3代表一个上传权限的ID,权限中有3则显示按钮 */

We registered a global direct command, using the method of vnode to access vue. code show as below:

//main.js
//按扭权限指令
Vue.directive('allow', {
  inserted: (el, binding, vnode) => {
    let permissionList = vnode.context.$route.meta.permission;
    if (!permissionList.includes(binding.value)) {
      el.parentNode.removeChild(el)
    }
  }
})

Thus far, access control process has been fully completed, and in the end we look at the complete flow chart of access control it.

Five complete routing control flowchart

flow chart

VI. References

  1. Vue + ElementUI hand line and website background management authority control
  2. Hand touch hands with you with the background of the control line and privileges vue

Guess you like

Origin www.cnblogs.com/jlfw/p/11837830.html