vue rights articles

Foreword

In one project, a number of important functions involve data management, to ensure data security, we will join in the project authority to limit each user's actions. As the front-end, back-end we have to do is fit to give permission to the data, do all sorts of restrictions on the page.

demand

Because this is a work of business needs, so for me there are two main local authority needs to be controlled.

The first is the side menu bar, you need to control the display and hidden.

The second is the individual buttons within a page, pop and so on.

Process

  1. How to get user rights?

    The back-end (user has permission to list the current) -> the front (get through the interface to the back-end, below we list the permissions of the current user named permissionList)

  2. How do the front limit?

    , Through demand for the product in the project point to configure permissions, and then to find out whether there is permission to configure point by permissionList, it has displayed no not displayed.

  3. and then?

    Gone.

When I first started receiving this needs time to think so, what is difficult, not to get permissionList Well then judge it. Later I discovered the real needs complicated than I imagined.

The real problem

The above mentioned needs of our problem can be solved within the side menu bar display & page operation.

Suppose we have such a set route (hereinafter just an example):

import VueRouter from 'vue-router'

/* 注意:以下配置仅为部分配置,并且省去了 component 的配置 */

export const routes = [

  {

    path: '/',

    name: 'Admin',

    label: '首页'

  },

  {

    path: '/user',

    name: 'User',

    label: '用户',

    redirect: { name: 'UserList' },

    children: [

      {

        path: 'list',

        name: 'UserList',

        label: '用户列表'

      },

      {

        path: 'group',

        name: 'UserGroup',

        label: '用户组',

        redirect: { name: 'UserGroupList' },

        children: [

          {

            path: 'list',

            name: 'UserGroupList',

            label: '用户组列表'

          },

          {

            path: 'config',

            name: 'UserGroupConfig',

            label: '用户组设置'

          }

        ]

      }

    ]

  },

  {

    path: '/setting',

    name: 'Setting',

    label: '系统设置'

  },

  {

    path: '/login',

    name: 'Login',

    label: '登录'

  }

]



const router = new VueRouter({

  routes

})

export default router

Of which the first two routes will be displayed in the sidebar, the third level will not appear in the sidebar.

Permissions within the page operation does not need to consider many other things, we analyze the main problem for the sidebar and routing, analysis, mainly the following questions:

  1. When acquiring permissionList, how to store permissionList
  2. Routing all gone when the child rights should not show itself (Example: When the list of users and groups of users do not have permission, the user should not be displayed in the sidebar)
  3. Redirect the default route in the absence of authority, should look for a redirection children have rights (Example: route users to redirect users to a list of routes, if the user does not have permission list, you should be redirected to the user group routing)
  4. When the user does not have permission directly enter the url of the need to jump to a page does not have permission or other operations. (Routing Restrictions)

Let us one by one to solve the above problems.

When obtaining permission, which is stored in & Routing Restrictions

I was here in beforeEach router get in, get the permissionList is located in a vuex in.

The reason is that taking into account the restrictions do routing, as well as to facilitate the use of the authority behind the project list, the following are examples of implementations:

First, we configure permissions added to the router:

// 以下只展示部分配置

{

  path: '/user',

  name: 'User',

  label: '用户',

  meta: {

    permissions: ['U_1']

  },

  redirect: { name: 'UserList' },

  children: [

    {

      path: 'list',

      name: 'UserList',

      label: '用户列表',

      meta: {

        permissions: ['U_1_1']

      }

    },

    {

      path: 'group',

      name: 'UserGroup',

      label: '用户组',

      meta: {

        permissions: ['U_1_2']

      },

      redirect: { name: 'UserGroupList' },

      children: [

        {

          path: 'list',

          name: 'UserGroupList',

          label: '用户组列表',

          meta: {

            permissions: ['U_1_2_1']

          }

        },

        {

          path: 'config',

          name: 'UserGroupConfig',

          label: '用户组设置',

          meta: {

            permissions: ['U_1_2_2']

          }

        }

      ]

    }

  ]

}

We can see the permissions applied on the meta, is easier to judge from router.beforeEch permissions, the permission is set to an array, because a page may involve more privileges.

Next we set router.beforeEach:

// 引入项目的 vuex

import store from '@/store'

// 引入判断是否拥有权限的函数

import { includePermission } from '@/utils/permission'



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

  // 先判断是否为登录,登录了才能获取到权限,怎么判断登录就不写了

  if (!isLogin) {

    try {

      // 这里获取 permissionList

      await store.dispatch('getPermissionList')

      // 这里判断当前页面是否有权限

      const { permissions } = to.meta

      if (permissions) {

        const hasPermission = includePermission(permissions)

        if (!hasPermission) next({ name: 'NoPermission' })

      }

      next()

    }

  } else {

    next({ name: 'Login' })

  }

})

We can see that we need a method to determine permissions & vuex in getPermissionList as follows:

// @/store

    export default {

      state: {

        permissionList: []

      },

      mutations: {

        updatePermissionList: (state, payload) => {

          state.permissionList = payload

        }

      },

      actions: {

        getPermissionList: async ({ state, commit }) => {

          // 这里是为了防止重复获取

          if (state.permissionList.length) return

          // 发送请求方法省略

          const list = await api.getPermissionList()

          commit('updatePermissionList', list)

        }

      }

    }
// @/utils/permission

import store from '@/store'



/**

 * 判断是否拥有权限

 * @param {Array<string>} permissions - 要判断的权限列表

 */

function includePermission (permissions = []) {

  // 这里要判断的权限没有设置的话,就等于不需要权限,直接返回 true

  if (!permissions.length) return true

  const permissionList = store.state.permissionList

  return !!permissions.find(permission => permissionList.includes(permission))

}

Redirection

How do we solve the above basic configuration and permissions route acquisition, how routing restrictions jump, then we have to deal with is the problem of redirection.

This may be related to our project architecture itself, under the sidebar of our project as well as children, are following figures show the tab switching, page after clicking Drug Administration normal circumstances will be redirected to storage management tab switching page, but when storage management do not have permission, it should simply redirects to a database management interface.

img

I would like to achieve the above results, I need to rewrite redirect router, so that you can dynamically determine (because at the time I did not know the current routing configuration permissions list of users)

Then I looked vue-router's documentation, found a redirect can be a way, so that you can redirect solve the problem.

vue-router redirect described in (https://router.vuejs.org/zh/guide/essentials/redirect-and-alias.html#%E9%87%8D%E5%AE%9A%E5%90%91) according to the instructions we can rewrite the redirect as follows:

// 我们需要引入判断权限方法

import { includePermission } from '@/utils/permission'



const children = [

  {

    path: 'list',

    name: 'UserList',

    label: '用户列表',

    meta: {

      permissions: ['U_1_1']

    }

  },

  {

    path: 'group',

    name: 'UserGroup',

    label: '用户组',

    meta: {

      permissions: ['U_1_2']

    }

  }

]



const routeDemo = {

  path: '/user',

  name: 'User',

  label: '用户',

  redirect: (to) => {

    if (includePermission(children[0].meta.permissions)) return { name: children[0].name }

    if (includePermission(children[1].meta.permissions)) return { name: children[1].name }

  },

  children

}

Although the problem has been solved, but found this to write down a lot of trouble, but also to modify router configuration, so we use a method to generate:

// @/utils/permission

/**

 * 创建重定向函数

 * @param {Object} redirect - 重定向对象

 * @param {string} redirect.name - 重定向的组件名称

 * @param {Array<any>} children - 子列表

 */

function createRedirectFn (redirect = {}, children = []) {

  // 避免缓存太大,只保留 children 的 name 和 permissions

  const permissionChildren = children.map(({ name = '', meta: { permissions = [] } = {} }) => ({ name, permissions }))

  return function (to) {

    // 这里一定不能在 return 的函数外面筛选,因为权限是异步获取的

    const hasPermissionChildren = permissionChildren.filter(item => includePermission(item.permissions))

    // 默认填写的重定向的 name

    const defaultName = redirect.name || ''

    // 如果默认重定向没有权限,则从 children 中选择第一个有权限的路由做重定向

    const firstPermissionName = (hasPermissionChildren[0] || { name: '' }).name

    // 判断是否需要修改默认的重定向

    const saveDefaultName = !!hasPermissionChildren.find(item => item.name === defaultName && defaultName)

    if (saveDefaultName) return { name: defaultName }

    else return firstPermissionName ? { name: firstPermissionName } : redirect

  }

}

Then we can be rewritten as:

// 我们需要引入判断权限方法

import { includePermission, createRedirectFn } from '@/utils/permission'



const children = [

  {

    path: 'list',

    name: 'UserList',

    label: '用户列表',

    meta: {

      permissions: ['U_1_1']

    }

  },

  {

    path: 'group',

    name: 'UserGroup',

    label: '用户组',

    meta: {

      permissions: ['U_1_2']

    }

  }

]



const routeDemo = {

  path: '/user',

  name: 'User',

  label: '用户',

  redirect: createRedirectFn({ name: 'UserList' }, children),

  children

}

Some of this a little simple, but I still need a route to a modification, so I wrote a recursive method to configure the router, and rewrite their redirect:

// @/utils/permission

/**

 * 创建有权限的路由配置(多级)

 * @param {Object} config - 路由配置对象

 * @param {Object} config.redirect - 必须是 children 中的一个,并且使用 name

 */

function createPermissionRouter ({ redirect, children = [], ...others }) {

  const needRecursion = !!children.length

  if (needRecursion) {

    return {

      ...others,

      redirect: createRedirectFn(redirect, children),

      children: children.map(item => createPermissionRouter(item))

    }

  } else {

    return {

      ...others,

      redirect

    }

  }

}

We only need to configure add this function in the outermost layer router will be able to:

import { createPermissionRouter } from '@/utils/permission'



const routesConfig = [

  {

    path: '/user',

    name: 'User',

    label: '用户',

    meta: {

      permissions: ['U_1']

    },

    redirect: { name: 'UserList' },

    children: [

      {

        path: 'list',

        name: 'UserList',

        label: '用户列表',

        meta: {

          permissions: ['U_1_1']

        }

      },

      {

        path: 'group',

        name: 'UserGroup',

        label: '用户组',

        meta: {

          permissions: ['U_1_2']

        },

        redirect: { name: 'UserGroupList' },

        children: [

          {

            path: 'list',

            name: 'UserGroupList',

            label: '用户组列表',

            meta: {

              permissions: ['U_1_2_1']

            }

          },

          {

            path: 'config',

            name: 'UserGroupConfig',

            label: '用户组设置',

            meta: {

              permissions: ['U_1_2_2']

            }

          }

        ]

      }

    ]

  }

]



export const routes = routesConfig.map(item => createPermissionRouter(item))



const router = new VueRouter({

  routes

})



export default router

Of course, write another advantage, in fact, you do not need to set the redirect, it will automatically redirect the first privileged route to the children of

Sidebar display issue

Our project is to use the sidebar to generate the routing configuration, of course, add some additional parameters to display the hierarchy and so on, do not write specific code here, and how to solve the sidebar all children without permission is not displayed the problem then.

My thinking here is that the routing configuration is also updated to vuex together, and then the sidebar configured to read from vuex configuration.

Because this place changes things a bit more involved, but also to the business, I will not put out the code, you can experiment on their own.

Facilitate the deployment of the team permission to point method

We solved the problem of most of the above rights, then there are many related to the deployment of business logic point of privilege, so to others on the team can be elegantly simple deployment point permissions to each page, I offer the following in the project ways to deploy permissions:

  1. Directly on a template provided by the v-permission instructions
<div v-permission="['U_1']"></div>
  1. By global methods this. $ Permission judgment, because some rights are not in the template of
{  
  hasPermission () {    
  // 通过方法 $permission 判断是否拥有权限    
  return this.$permission(['U_1_1', 'U_1_2'])  
}}

It is noted here, $ permission to the return value is monitored, from the need to determine in this $ store is determined, to achieve the following code:

// @/utils/permission

    /**

     * 判断是否拥有权限

     * @param {Array<string|number>} permissions - 要判断的权限列表

     * @param {Object} permissionList - 传入 store 中的权限列表以实现数据可监测

     */

    function includePermissionWithStore (permissions = [], permissionList = []) {

      if (!permissions.length) return true

      return !!permissions.find(permission => permissionList.includes(permission))

    }
import { includePermissionWithStore } from '@/utils/permission'

export default {

  install (Vue, options) {

    Vue.prototype.$permission = function (permissions) {

      const permissionList = this.$store.state.permissionList

      return includePermissionWithStore(permissions, permissionList)

    }

  }

}

The following code instructions to implement (in order not to conflict with v-if, where the control mode display hidden by the addition / removal of className):

// @/directive/permission

import { includePermission } from '@/utils/permission'

const permissionHandle = (el, binding) => {

  const permissions = binding.value

  if (!includePermission(permissions)) {

    el.classList.add('hide')

  } else {

    el.classList.remove('hide')

  }

}

export default {

  inserted: permissionHandle,

  update: permissionHandle

}

to sum up

For the previous question, the following summary:

  1. When acquiring permissionList, how to store permissionList

    router.beforeEach capture, store in vuex.

  2. Routing all gone when the child rights should not show itself (Example: When a user lists and user permissions are not set, the user should not be displayed in the sidebar)

    Configuring the route by storing the vuex generated sidebar provided, arranged to control the display & vuex Hide and modified acquisition permission.

  3. Redirect the default route in the absence of authority, should look for a redirection children have rights (Example: route users to redirect users to a list of routes, if the user does not have permission list, you should be redirected to the user group routing)

    Function redirect is set by vue-router be achieved

  4. When the user does not have permission directly enter the url of the need to jump to a page does not have permission or other operations. (Routing Restrictions)

    Set permissions in the meta, router.beforeEach the judge permission.

Guess you like

Origin www.cnblogs.com/amysu/p/10951067.html