管理系统-权限那点东西

175 阅读5分钟

浅谈管理系统中关于菜单、路由、按钮权限的实现过程

世界管理系统千千万,每个系统都可能有不同的权限管理方式,代码变化万千,但万变不离其宗

一、什么是权限

  • 现代系统肯定会有这些操作:
    • 登录:要知道,计算机是不知道你是谁的,而登录就是为了记录你的状态信息,只有在成功后,才会给用户颁发一个独立的签名--token,它记录着用户的登录信息、登录时间等等。当拿到这个签名后,只有携带这张身份证才可获得想要访问的数据内容。
    • 跳转:登录成功后不可能一直给用户展示登录页面吧?跳转页面是接下来的最重要的方式,况且用户的目的就是为了访问系统里面的内容
    • 展示:需要向用户展示什么内容?需要为用户提供什么功能?需要用户怎么操作?这些都是有关权限的东西
  • 要知道,管理系统并非每个人使用都一样的,某些敏感保密的数据是不会让所有人看到的,每个人/岗位就应该做自己该做的事。
  • 并且繁杂的大型管理系统,可能对于某些使用人员只需关注自己所在意的功能即可
  • 如何限制这些问题,就需要权限来管理,在系统层面/代码层面就进行限制

二、现代关于权限的痛点

  • 对我来说,我接触过很多管理系统的研发、维护工作,总结几点就是
    • 有的对权限一点都不理解,完全没经过设计就写
    • 有的系统权限写的一塌糊涂,全由前端代码来限制
    • 有的代码写的一塌糊涂,这一点那一点完全不能看,不给人维护的机会

三、设计

  • 进入主题,开始上才艺
  • 管理系统中权限系统搭建可以简单分为三个部分
    • 菜单:控制所有的路由、菜单、按钮、权限值等记录信息
    • 角色:每个角色都有每个角色对应的菜单系统,可以划分不同角色配置不同的菜单/按钮等权限
    • 用户:每个用户挂载不同的角色,根据角色加载有对应权限的数据

3.1、动态路由

  • 以vue3为例,通过vue-router@4.xaddRoute,可以很方便的实现这个需求
  • 菜单管理记录着每个菜单的路由信息,在用户登录后,根据角色可获取到对应角色的菜单数据
  • 前端开发人员拿到数据后,根据每个对象去遍历查找,动态添加路由
// 路由信息,可根据webpack/vite 动态导入,最后获得的结果
const home = {
    path: '/home‘,
    name: 'Home',
    component: () => import('@/views/Home.vue')
}
const about =  {
    path: '/about‘,
    name: 'About',
    component: () => import('@/views/About.vue')
}

export default [home, about]
// 菜单数据
import dynamicRoutes from './dynamic-routes.js'
import router from '@/router';

const menus = [{ route: '/home', ...}, { route: '/about', ...}]

// 前端记录的每个路由信息 注:没有添加到初始化routes中

// 设计函数,根据菜单数据,映射动态路由
const patchRoutes = (menus) => {
    menus.forEach(menu => {
        const resultRoute = dynamicRoutes.find(item => item.path === menu.route)
        if (resultRoute) {
            router.addRoute(resultRoute)
        }
    })
}

// 加载菜单数据接口的方法调用
patchRoutes(menus)

  • 上面是一个简单的根据菜单注册动态路由的过程,可根据具体业务需求在做操作

3.2、按钮权限

  • 如何判断按钮是否展示,这一步在前面的菜单管理已经设计好了,菜单管理记录着每个路由下的按钮信息(只做记录),包括按钮权限值

  • 当在角色数据中添加该菜单下的按钮后,即可完整的获取该角色对有权限的按钮数据的权限值

    • 通常前端只需要定义权限值,推荐 模块名:按钮操作,例如:menu:delete
    • 前端需要在代码层面根据这个权限值判断是否展示这个按钮
    • 后端需要提供根据角色查询出来的权限值所有数据
  • 在vue3中,可以根据指令,来完成这个按钮的显隐操作

<template>
   <div class="test-permission">
       <button v-permission="'home:delete'">删除按钮</button>
   </div>
</template>

<script setup lang="ts">
// 这块拿到permission 数据
const permissions = ['home:delete', 'about:delete', ....]

const vPermission = {
  mounted(el: HTMLElement, binding: any, vnode: VNode) {
    if (!permissions.includes(binding.value) {
        // 说明没有权限,移除节点
        el.parentElement?.removeChild(el)
    }
  }
}
</script>

3.3、优缺点

  • 优点:

    • 逻辑清晰,可维护性强
    • 可以完全实现前端路由状态具体化,限制不可访问的人员进行访问
    • 可根据需求写一个自动生成工具(如果感兴趣,后续可能会写相关文章)
  • 缺点:

    • 需要编写的文件/定义的变量比较繁琐
    • 权限值如有规律的话,可能会被个别有心人员破解,所以需要后端开发人员在后端根据按钮权限值对接口权限进行控制
    • 按钮权限值一经定义,不可修改,这点是个设计缺陷,但目前来说,限制角色修改权限,可以解决这个问题

四、总结

  • 权限管理设计是作为一个开发人员必经之路,如何设计,如何巧妙地用最少得缺陷解决最大的问题,这个需要好好反思
  • 代码质量一定要过关!!!毕竟谁都不想维护看不懂的东西
  • 文章可能写的有点潦草,可以借鉴,代码验证过没问题,有问题可以一起讨论