企业级权限系统设计:ant-design-vue-pro细粒度权限控制实现

企业级权限系统设计:ant-design-vue-pro细粒度权限控制实现

【免费下载链接】ant-design-vue-pro 【免费下载链接】ant-design-vue-pro 项目地址: https://gitcode.com/gh_mirrors/antd/ant-design-vue-pro

在企业级应用开发中,权限管理是保障系统安全的核心环节。随着业务复杂度提升,传统基于角色的权限控制(RBAC)已难以满足多维度、精细化的权限需求。本文将深入剖析ant-design-vue-pro如何实现从页面访问到按钮操作的全链路权限控制,通过具体代码实现与架构设计,为开发者提供可落地的企业级权限解决方案。

权限系统整体架构

ant-design-vue-pro采用三层权限控制模型,实现从宏观到微观的权限粒度覆盖:

  • 路由权限:控制页面级别的访问权限,基于用户角色动态生成可访问路由表
  • 功能权限:控制按钮、表单等交互元素的操作权限,实现细粒度功能控制
  • 数据权限:控制列表展示数据范围,基于用户权限过滤数据行

权限控制三层模型

核心权限控制逻辑分散在以下关键文件中:

权限定义与数据结构

系统首先定义了标准化的权限枚举与数据结构,为统一权限控制奠定基础。在src/core/permission/permission.js中,定义了基础操作权限集合:

export const PERMISSION_ENUM = {
  'add': { key: 'add', label: '新增' },
  'delete': { key: 'delete', label: '删除' },
  'edit': { key: 'edit', label: '修改' },
  'query': { key: 'query', label: '查询' },
  'get': { key: 'get', label: '详情' },
  'enable': { key: 'enable', label: '启用' },
  'disable': { key: 'disable', label: '禁用' },
  'import': { key: 'import', label: '导入' },
  'export': { key: 'export', label: '导出' }
}

这种枚举设计确保了权限标识的一致性,便于系统统一处理权限判断逻辑。每个权限包含key(权限标识)和label(显示名称)两个属性,兼顾了程序处理与用户展示需求。

用户权限加载流程

用户登录后,系统通过GetInfo action加载用户权限信息,并进行格式化处理。在src/store/modules/user.js中:

// 获取用户信息
GetInfo ({ commit }) {
  return new Promise((resolve, reject) => {
    getInfo().then(response => {
      const { result } = response
      if (result.role && result.role.permissions.length > 0) {
        const role = { ...result.role }
        // 格式化权限数据结构
        role.permissions = result.role.permissions.map(permission => ({
          ...permission,
          actionList: (permission.actionEntitySet || {}).map(item => item.action)
        }))
        role.permissionList = role.permissions.map(permission => permission.permissionId)
        
        commit('SET_ROLES', role)
        commit('SET_INFO', result)
        // ...其他状态更新
        resolve(result)
      } else {
        reject(new Error('getInfo: roles must be a non-null array !'))
      }
    }).catch(error => {
      reject(error)
    })
  })
}

这段代码将后端返回的权限数据转换为前端可用的格式,特别是将权限动作列表(actionList)提取为数组形式,便于后续权限判断。处理后的数据结构如下:

{
  "role": {
    "permissions": [
      {
        "permissionId": "user",
        "actionList": ["add", "edit", "delete", "query"]
      },
      {
        "permissionId": "role",
        "actionList": ["query", "edit"]
      }
    ],
    "permissionList": ["user", "role"]
  }
}

路由权限控制实现

路由权限控制通过导航守卫实现,在用户访问页面时动态校验权限并生成路由表。核心逻辑在src/permission.js中:

router.beforeEach((to, from, next) => {
  NProgress.start()
  const token = storage.get(ACCESS_TOKEN)
  
  if (token) {
    if (to.path === loginRoutePath) {
      next({ path: defaultRoutePath })
      NProgress.done()
    } else {
      if (store.getters.roles.length === 0) {
        // 加载用户信息和权限
        store.dispatch('GetInfo').then(res => {
          // 根据权限生成可访问路由
          store.dispatch('GenerateRoutes', { token, ...res }).then(() => {
            resetRouter()
            store.getters.addRouters.forEach(r => {
              router.addRoute(r)
            })
            // 处理重定向
            const redirect = decodeURIComponent(from.query.redirect || to.path)
            next({ path: redirect })
          })
        }).catch(() => {
          // 权限获取失败处理
          store.dispatch('Logout').then(() => {
            next({ path: loginRoutePath, query: { redirect: to.fullPath } })
          })
        })
      } else {
        next()
      }
    }
  } else {
    if (allowList.includes(to.name)) {
      next()
    } else {
      next({ path: loginRoutePath, query: { redirect: to.fullPath } })
      NProgress.done()
    }
  }
})

路由守卫实现了以下关键功能:

  1. 未登录用户重定向到登录页
  2. 已登录用户首次访问时加载权限并生成路由
  3. 动态添加有权限访问的路由
  4. 处理登录后的重定向逻辑

通过这种方式,系统确保用户只能访问其权限范围内的页面,从宏观层面控制访问权限。

细粒度功能权限控制

功能权限控制实现按钮级别的权限管理,通过自定义Vue指令v-auth实现。在src/core/permission/permission.js中定义了权限判断方法:

function plugin (Vue) {
  if (plugin.installed) {
    return
  }

  !Vue.prototype.$auth && Object.defineProperties(Vue.prototype, {
    $auth: {
      get () {
        const _this = this
        return (permissions) => {
          const [permission, action] = permissions.split('.')
          const permissionList = _this.$store.getters.roles.permissions
          return permissionList.find((val) => {
            return val.permissionId === permission
          }).actionList.findIndex((val) => {
            return val === action
          }) > -1
        }
      }
    }
  })
}

在组件中使用方式如下:

<a-button v-if="$auth('user.add')" type="primary" @click="handleAdd">新增用户</a-button>
<a-button v-if="$auth('user.edit')" @click="handleEdit">编辑</a-button>
<a-button v-if="$auth('user.delete')" type="danger" @click="handleDelete">删除</a-button>

这种实现方式具有以下优势:

  • 侵入性低,通过v-if指令自然融入模板
  • 语义清晰,直接在模板中体现权限控制逻辑
  • 粒度精细,可控制到单个按钮的显示与隐藏

表格组件的权限集成

在数据列表场景中,权限控制更为复杂,需要同时处理行级别操作权限和批量操作权限。ant-design-vue-pro的Table组件对此进行了深度集成:

src/components/Table/index.js实现了选中行跟踪与权限联动:

updateSelect (selectedRowKeys, selectedRows) {
  this.selectedRows = selectedRows
  this.selectedRowKeys = selectedRowKeys
  const list = this.needTotalList
  this.needTotalList = list.map(item => {
    return {
      ...item,
      total: selectedRows.reduce((sum, val) => {
        const total = sum + parseInt(get(val, item.dataIndex))
        return isNaN(total) ? 0 : total
      }, 0)
    }
  })
}

结合权限控制后,表格批量操作按钮状态会根据选中行和用户权限动态变化:

<a-button 
  v-if="$auth('order.export')" 
  :disabled="selectedRowKeys.length === 0"
  @click="handleExport"
>
  导出选中
</a-button>

这种设计确保用户只能看到并使用其有权限的功能,同时根据实际选择数据动态调整按钮状态。

权限系统最佳实践

基于ant-design-vue-pro的权限实现,总结以下企业级权限系统设计最佳实践:

  1. 权限粒度分层:采用路由-功能-数据三级权限控制,覆盖不同场景需求
  2. 权限数据标准化:统一权限标识格式,如"资源.操作"的命名规范
  3. 权限判断集中化:将权限判断逻辑封装为公共方法,避免散落各地
  4. 前端权限弱化:前端权限仅做展示控制,核心权限验证必须在后端实现
  5. 权限状态管理:使用Vuex集中管理权限状态,确保状态一致性
  6. 错误处理完善:对权限获取失败、令牌过期等异常情况做优雅处理

通过这套权限控制体系,ant-design-vue-pro成功实现了从页面访问到按钮操作的全链路权限管理,为企业级应用提供了坚实的安全基础。开发者可根据实际业务需求,在此基础上扩展更复杂的权限场景,如数据行级权限、数据字段权限等高级功能。

【免费下载链接】ant-design-vue-pro 【免费下载链接】ant-design-vue-pro 项目地址: https://gitcode.com/gh_mirrors/antd/ant-design-vue-pro

创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值