# web系统中的权限控制

六七年前,web系统中一般会有一个专门的403页面,用来阻止用户访问没有权限的页面或者操作,用户访问了没有权限的页面,由后端重定向到403页面。随着web技术发展,前端交互越来越多,权限控制越来越细,尤其B端web产品,一个系统可能有多达几十个角色,每个角色拥有不同的权限,一个用户对应一种角色,通过对角色权限的划分来控制用户权限,权限控制需要细分到页面上的操作按钮,如果再依靠以前那种页面跳转的交互方式来控制权限,未免太过低效,如何依靠前端实现权限控制,提高效率又能便于开发和管理呢?

对前端来说,权限控制分两种,第一种是页面级的,第二种是按钮级别的。

# 控制路由

第一种比较简单,按模块划分用户权限,隐藏没有权限的页面导航,再在路由层面增加权限判断,拦截越权页面路由。

举例,假如页面路由path是/user,某用户没有user页面权限,对应权限值为user: false

const router = new VueRouter({ ... })
// 当前用户权限列表
const permission = {
  // 模块权限
  user: false
}
router.beforeEach((to, from, next) => {
  // 路由path和权限对应
  if( !permission[to.path] ){
    next('/403')
  }
  next();
})

如果不想把权限直接和path关联,也可以把权限信息写到路由配置的meta

const router = new VueRouter({
  routes: [
    {
      path: '/user',
      component: User,
      meta: {
        permission: 'user'
      }
    }
  ]
})
// 当前用户权限列表
const permission = {
  // 模块权限
  user: false
}
router.beforeEach((to, from, next) => {
  // 没有权限,跳转到403页面
  if( !permission[to.meta.permission] ){
    next('/403')
  }
  next();
})

# 控制按钮

第二种,对页面某个操作按钮做权限判断。

举个例子,根据网络实名制规定,用户在网站跟帖评论必须实名制,为了引导未实名用户参与评论,又不能直接对其隐藏评论功能,这时候就要引入权限,区分已实名与未实名用户,在“提交评论”按钮上做权限判断。一个web系统中要做权限判断的地方往往有很多,如果对每个按钮绑定事件回调,工作量太大,同时也不好维护,更好的做法是,使用自定义指令

import { Message } from 'element-ui'
// 当前用户权限列表
const permission = {
  // 模块权限
  user: false
}
// 注册一个全局自定义指令 `v-permission`
Vue.directive('permission', {
  bind: function (el, binding) {
    // 点击时判断权限
    el.addEventListener('click', () => {
      if (!permission[binding.value] ){
        Message.error('无权限')
      }
    }, false)
  }
})

使用

<button v-permission="'user'" @click="submit">提交评论</button>

你会发现点击按钮,submit同时也触发了,为了解决这个问题,需要把submit放到权限判断之后去执行

<button v-permission="{
  value: 'user',
  click: submit
}">提交评论</button>
import { Message } from 'element-ui'
// 当前用户权限列表
const permission = {
  // 模块权限
  user: false
}
// 注册一个全局自定义指令 `v-permission`
Vue.directive('permission', {
  bind: function (el, binding) {
    let { value, click } = binding.value;
    // 点击时判断权限
    el.addEventListener('click', () => {
      if (!permission[value] ){
        Message.error('无权限')
        return false;
      }
      click();
    }, false)
  }
})

# 禁用按钮

某些情况下,需要禁用无权限的操作

<button v-permission="{
  value: 'user',
  disabled: true
}">提交评论</button>
// js
import { Message } from 'element-ui'
// 当前用户权限列表
const permission = {
  // 模块权限
  user: false
}
// 注册一个全局自定义指令 `v-permission`
Vue.directive('permission', {
  bind: function (el, binding) {
    let { value, disabled } = binding.value;

    if (!permission[value] ){
      el.setAttribute('disabled', disabled)
    }
  }
})
上次更新: 10/23/2021, 10:33:11 PM