Skip to content

前端权限怎么设计? ​

权限分成路由、操作和数据三层。前端决定「看不看得到」,接口决定「做不做得到」。只隐藏按钮,等于没有权限。

原理 ​

常见模型是 RBAC:用户对应角色,角色对应一组权限点,例如 order:read、order:export。登录成功后拿到当前用户的权限列表。权限点用字符串而不是写死角色名,这样新增角色不必改每一处判断。

路由。 路由表写上 meta.permission。导航守卫里没有权限就进 403 或首页,而不是把页面渲染出来再藏。动态路由可以从后端下发菜单,再映射到前端已经存在的页面组件。不要直接执行后端返回的组件路径或代码。

操作。 按钮、列、批量操作包一层判断:

jsx
function Can({ permission, children }) {
  const { permissions } = useCurrentUser()
  if (!permissions.includes(permission)) return null
  return children
}

数据。 列表接口按当前用户过滤行和字段。前端拿到不该看的字段后再藏起来,数据已经离开了服务器。导出、删除、改状态各自有自己的权限点,不复用「能看列表」。

令牌放在 HttpOnly Cookie 或按 本地存储 里的取舍放置。权限列表可以放内存,刷新后随用户信息重新拉取。

追问 ​

前端路由守卫能当安全边界吗?

不能。守卫只改善体验,请求不经过它。任何写操作都要在服务端再查一次这个用户是否拥有该权限点。

权限很多,判断写在每一页会怎样?

把「是否拥有某个权限点」收成一个函数或组件。页面只声明自己要的权限点,不自己解析角色。角色和权限点的对应关系放在服务端,前端只消费结果。

易错点 ​

  • 用 v-if="role === 'admin'" 散落在项目里。角色一调整就要改模板。
  • 菜单没显示就认为接口安全。
  • 只在进入路由时读了一次权限,管理员在后台收回权限后,已经打开的页面还能继续操作。敏感操作前以接口结果为准。

相关 ​