权限管理

XYGo Admin 2025-02-20 299 次阅读

RBAC 角色权限 + 按钮级权限 + 字段级权限的完整体系

权限管理

XYGo Admin 实现了三级权限控制体系,从粗到细覆盖所有场景。

一、角色权限(RBAC)

基于角色的访问控制,管理员通过角色关联菜单权限。

角色类型

| 角色标识 | 说明 |

|---------|------|

| R_SUPER | 超级管理员,拥有所有权限,不受权限校验限制 |

| R_ADMIN | 普通管理员,权限由分配的菜单决定 |

| 自定义 | 可创建任意角色并分配菜单权限 |

权限分配流程

  1. 创建角色

  2. 为角色分配菜单(勾选菜单树)

  3. 将角色分配给用户

  4. 用户登录后,后端返回该角色可访问的菜单列表

  5. 前端根据菜单列表动态注册路由

多角色支持

用户支持绑定多个角色(admin_user_role 多对多表),权限取并集。角色还支持父子继承关系,子角色自动继承父角色的所有菜单权限。

二、按钮级权限

精确控制页面中每个操作按钮的显隐,并在后端拦截未授权的 API 请求。

后端配置

在菜单管理中,为页面菜单添加「按钮」类型的子节点:

  • 菜单类型:按钮

  • 权限标识:如 addeditdeleteexport

  • 权限点(perms):关联的 API 路径,如 ["POST /admin/member/group/save"]

前端按钮隐藏

通过 v-auth 指令控制按钮显隐:

vue 复制代码
<template>

  <!-- 只有拥有 add 权限的角色才能看到此按钮 -->

  <ElButton v-auth="'add'" type="primary">新增</ElButton>

  <ElButton v-auth="'edit'" type="primary">编辑</ElButton>

  <ElButton v-auth="'delete'" type="danger">删除</ElButton>

</template>

也可以在 JS 中使用:

typescript 复制代码
const { hasAuth } = useAuth()

if (hasAuth('add')) {

  // 显示新增按钮

}

后端 API 拦截(v1.3.6+)

AdminPermission 中间件基于菜单的 perms 字段,在 API 层面强制校验权限:

  1. 拼接请求的 METHOD + PATH(如 POST /admin/member/group/save

  2. 查缓存:该 API 是否被某个按钮菜单的 perms 关联

  3. 如果无关联,说明不需要按钮权限控制,直接放行

  4. 如果有关联,检查当前用户的角色是否绑定了对应的按钮菜单

  5. 未绑定则返回 403(无操作权限)

add/edit 共享接口的精确鉴权:当新增和编辑按钮共享同一个 save 接口时,中间件会根据请求体中的 id 字段区分操作类型——无 id 为新增,有 id 为编辑,分别检查对应按钮的权限。

三、字段级权限(v1.3.6+)

控制数据字段的可见性和可编辑性,适用于敏感数据保护。

配置方式

在后台「角色管理」→「字段权限」中:

  1. 选择目标资源(如 member_group)

  2. 配置每个字段对该角色的权限:

    • 不可见:该角色看不到此字段(列表不显示、详情隐藏)

    • 只读:该角色可以看到但不能修改此字段

    • 可编辑:该角色拥有完全权限(默认)

前端自动生效

字段权限通过 useFieldPerm hook 集成到 useTable 中,所有使用 useTable 的页面自动生效,无需逐页修改:

  • 用户登录时,前端调用 fieldPerm/mine 接口一次性获取当前用户的字段权限

  • useTablecolumnsFactory 自动过滤掉不可见字段的列

  • 多角色取并集:同一字段在不同角色中有不同权限时,取最高权限

typescript 复制代码
// 也可以在自定义场景中手动使用

const { isFieldVisible, isFieldReadonly, filterColumns } = useFieldPerm('admin_user')



// 过滤表格列

const visibleColumns = filterColumns(allColumns)



// 判断单个字段

if (isFieldReadonly('mobile')) {

  // 手机号只读

}

后端工具函数

提供 fieldperm 包用于后端字段过滤:

go 复制代码
import "xygo/internal/library/fieldperm"



// 查询时过滤不可见字段

data = fieldperm.FilterResponseFields(ctx, "admin_user", data)



// 写入时获取需要剔除的字段

blocked := fieldperm.FilterWriteFields(ctx, "admin_user")

代码生成器适配

代码生成器自动为新模块的页面菜单填充 resource 字段(关联数据表名),生成的模块无需手动配置即可使用字段权限。

权限校验流程

复制代码
请求到达

  → AdminAuth 中间件

    → 解析 JWT Token

      → 获取用户角色

        → R_SUPER?直接放行

        → AdminPermission 中间件

          → 请求 API 是否有按钮权限关联?

            → 无关联:放行(不需要按钮权限控制的接口)

            → 有关联:检查用户角色是否绑定了该按钮

              → 有权限:继续处理

              → 无权限:返回 403