导读:本期聚焦于张立峰创作的《Vue 3 低代码平台如何实现角色权限与数据权限双重控制?》,敬请观看详情。角色权限和数据权限是低代码平台绕不开的两道坎。只做了菜单级控制,用户还能通过接口越权访问别人的数据,这类问题在实际项目里屡见不鲜。本文基于 Vue 3 组合式 API,完整拆解一套权限体系的设计思路:前端路由如何配合后端返回的菜单树做动态注册,按钮级权限怎样通过自定义指令统一收口,数据权限又该如何用行级过滤方案落地。文中还分析了纯前端校验的安全隐患,说明为什么权限必须前后端配合,并给出权限缓存、路由刷新等常见坑位的解决办法,适合正在搭建中后台系统的开发者参考。

低代码平台的权限问题比传统后台系统更棘手。传统系统的页面和接口相对固定,写死几个角色判断就够了;而低代码平台的表单、列表、按钮都是运行时动态生成的,权限必须跟着元数据走,不能跟着代码走。很多团队在第一版只做了菜单权限,上线后发现用户虽然看不到某个按钮,却可以直接调接口改别人的数据,这就是典型的只做了功能权限、漏了数据权限。本文围绕 Vue 3 的组合式 API,把角色权限和数据权限的完整链路捋一遍。

Vue 3 低代码平台如何实现角色权限与数据权限双重控制?

一、权限体系整体设计:前端管体验,后端管安全

先明确一个原则:前端权限控制的目的是用户体验,不是安全。任何只在前端做的权限拦截,用户打开浏览器开发者工具就能绕过。所以整个体系要分两层:前端负责根据角色渲染对应的菜单、按钮和数据范围,让用户看不到不该看的东西;后端在每一个接口入口处校验角色和数据归属,保证即使前端被绕过,数据也拿不到。

在这个前提下,权限模型通常拆成三个概念:角色是权限的集合,比如管理员、运营、普通员工;功能权限指能不能执行某个操作,对应菜单、页面、按钮;数据权限指能操作哪些范围的数据,比如只能看自己创建的订单、只能看本部门的客户。低代码平台的特点是页面和按钮都是元数据驱动的,所以功能权限最好绑定在元数据的 permission 字段上,而不是写死在代码里。

权限数据的下发时机也有讲究。推荐在用户登录后,由后端一次性返回该用户拥有的完整权限标识列表,前端存入 Pinia。这样路由守卫和按钮指令都能同步判断,避免每个组件各自请求权限接口造成的抖动。

二、动态路由与菜单权限的实现

Vue 3 里推荐用 createRouter 加路由守卫的组合方案。基础思路是:路由表分静态和动态两部分,静态路由放登录页、404 页这类所有人可见的页面;动态路由根据后端返回的菜单树,在登录成功后用 router.addRoute 注册。这样改角色权限只需要改后端配置,前端不用重新发版。

核心代码大概是这样的结构:

const routes = [
  { path: '/login', component: Login }
]

const router = createRouter({
  history: createWebHistory(),
  routes
})

router.beforeEach(async (to, from) => {
  const userStore = useUserStore()
  if (!userStore.token) return '/login'
  // 动态路由只注册一次
  if (!userStore.routesAdded) {
    const menus = await fetchUserMenus()
    buildRoutes(menus).forEach(route => router.addRoute(route))
    userStore.routesAdded = true
    // addRoute 后需要重新跳转一次才能命中新路由
    return { ...to, replace: true }
  }
  if (!to.matched.length) return '/404'
})

这里有个高频坑:addRoute 是异步生效的,第一次注册完动态路由后,当前导航已经解析完了,必须用 return { ...to, replace: true } 重新触发一次导航,否则会白屏或者直接掉进 404。另外 404 路由要放在动态路由注册之后再匹配,或者用通配写法兜底,不能写死在静态路由最前面。

菜单渲染则直接消费后端返回的菜单树,用递归组件生成 el-menu 或自定义侧边栏。菜单项上带上权限标识,如果后端已经按角色过滤过菜单树,前端甚至不需要再判断,直接渲染即可,这样逻辑最简单。

三、按钮级权限:自定义指令统一收口

页面内的按钮权限如果靠每个组件里写 v-if="hasPermission('order:delete')",代码会散落各处,后期梳理权限点非常痛苦。更优雅的方式是封装一个自定义指令 v-permission,统一从 Pinia 的权限集合里判断,没有权限时直接把元素从 DOM 中移除。

// directives/permission.js
export const permission = {
  mounted(el, binding) {
    const userStore = useUserStore()
    const { value } = binding
    if (!value) return
    const has = Array.isArray(value)
      ? value.some(p => userStore.permissions.includes(p))
      : userStore.permissions.includes(value)
    if (!has) {
      el.parentNode && el.parentNode.removeChild(el)
    }
  }
}

// 使用方式
// <el-button v-permission="'order:delete'">删除订单</el-button>
// <el-button v-permission="['order:export', 'order:audit']">导出或审核</el-button>

低代码平台的表单渲染器可以更进一步:在解析页面元数据时,遇到按钮组件自动读取其 permission 字段并挂上指令,业务方配置表单时勾选权限点即可,完全不用碰代码。需要注意指令方式是直接删 DOM,如果只是想禁用而不是隐藏,可以改成一个组合式函数 usePermission,返回布尔值后用 :disabled 绑定,交互上更友好,用户能感知到功能存在但无权操作。

四、数据权限:行级过滤怎么做

数据权限是很多团队容易漏掉的部分。常见的数据范围有四档:全部数据、本部门、本部门及下级、仅本人。落到实现上,前端和后端各有一份工作。后端在查询接口里根据用户角色拼接过滤条件,比如给 SQL 注入 create_by = 用户ID 或者 dept_id IN (部门集合);前端则在列表页把过滤条件同步传给接口,并且隐藏无权数据的操作按钮。

在低代码平台里,数据权限可以做成元数据配置。每个列表模型定义一个数据范围字段,运行时根据当前用户的部门和角色动态计算过滤参数。示意的查询参数大概是这样:

// 根据角色计算数据范围参数
function buildDataScope(userStore) {
  switch (userStore.dataScope) {
    case 'all':
      return {} // 不加过滤,后端管理员角色放行
    case 'dept':
      return { deptId: userStore.deptId }
    case 'deptAndChild':
      return { deptIdPath: userStore.deptIdPath } // 如 /1/12/120/
    case 'self':
      return { createBy: userStore.userId }
  }
}

// 列表查询时合并参数
const params = { page: 1, size: 20, ...buildDataScope(userStore) }

部门树用路径编码(如 /1/12/120/)是比递归查子部门更高效的方案,一次 LIKE '/1/12/%' 就能查出本部门及全部下级,避免每次查询都递归展开部门树。另外要强调一点:这些过滤参数只是给后端的提示,后端必须独立校验,不能信任前端传来的 deptId,否则攻击者改一下参数就能越权拉取全量数据。

五、常见坑与优化建议

第一是权限缓存问题。权限列表存在 Pinia 里,用户切换角色或管理员修改权限后,前端不会自动感知。简单做法是权限变更后强制相关用户重新登录;体验更好的做法是后端推送变更事件,前端重新拉取权限并重建路由,重建前记得调用 router.removeRoute 清掉旧路由。

第二是按钮指令的时序问题。v-permissionmounted 里移除元素,如果父组件后续还操作该元素可能报错,必要时可以在 beforeMount 里置为隐藏,或在指令里同时处理 updated 钩子应对权限动态变化的场景。

第三是权限点命名规范。建议统一用 模块:资源:操作 的三段式,比如 order:list:export,前后端共用同一套标识。低代码平台的权限点最好由页面设计器在保存元数据时自动登记到权限表中,避免手工维护出现遗漏。把这些细节提前定好,权限体系后期扩展才不会失控。

Vue 3低代码平台权限控制修改时间:2026-09-05 18:49:01

免责声明:已尽一切努力确保本网站所含信息的准确性。网站作品多为原创整理与精心创作,观点力求客观中立。本站旨在免费分享,内容仅供个人学习、研究或参考使用。若引用了第三方作品,版权归原作者所有。如内容涉及您的权益,请联系我们进行处理Email:chomcom@qq.com。
引用或转载本作品时,请注明当前出处:https://www.ipipp.com/html/20260905/51077.html,基于非商业用途的前提下,欢迎转载或二创本作品。
内容垂直聚焦
专注技术核心技术栏目,确保每篇文章深度聚焦于实用技能。从代码技巧到架构设计,为用户提供无干扰的纯技术知识沉淀,精准满足专业提升需求。
知识结构清晰
覆盖从开发到部署的全链路。AI、前端、编程、数据库、服务器、建站、系统层层递进,构建清晰学习路径,帮助用户系统化掌握开发与运维所需的核心技术。
深度技术解析
拒绝泛泛而谈,深入技术细节与实践难点。无论是数据库优化还是服务器配置,均结合真实场景与代码示例进行剖析,致力于提供可直接应用于工作的解决方案。
专业领域覆盖
精准对应开发生命周期。从前端界面到后端编程,从数据库操作到服务器运维,形成完整闭环,一站式满足全栈工程师和运维人员的技术需求。
即学即用高效
内容强调实操性,步骤清晰、代码完整。用户可根据教程直接复现和应用于自身项目,显著缩短从学习到实践的距离,快速解决开发中的具体问题。
持续更新保障
专注既定技术方向进行长期、稳定的内容输出。确保各栏目技术文章持续更新迭代,紧跟主流技术发展趋势,为用户提供经久不衰的学习价值。