Become a sponsor

概述
前端权限是按钮级 UX 控制:directives/permission.ts 按 getUser 返回的 permissions 数组控制元素显隐;超管通配权限 *:*:* 直接放行。后端接口级校验是强制层(403),前端指令只是体验层。
登录 → GetInfo(/api/index/getUser)
→ userInfo.permissions(后端 LoadIdentity 的 Perms)
超管 = ["*:*:*"](通配)
→ store 缓存 → 指令消费后端 Perms 来源:role_menu → menu(type=1 且 status=0 且 hide=0)的 permission 去重集合(详见 5.4 权限管理(RBAC))。
按钮级控制(语义示意):
<el-button v-permission="'sys:user:add'">新增</el-button>
指令逻辑:
permissions 含 "*:*:*" → 放行(超管)
permissions 含传入权限码 → 放行
否则 → 移除元素(v-if 等效)后端 gmeta permission:"sys:user:add"
↔ 前端指令 v-permission="'sys:user:add'"
↔ 菜单权限节点 permission=sys:user:add
↔ 角色已勾选该节点
四处必须一致——不一致的表现:
前端可见按钮但后端 403 → 节点存在但角色未勾选(或身份缓存旧)
前端按钮消失但后端有权限 → permissions 缓存旧 / 指令码拼错| 层 | 位置 | 性质 |
|---|---|---|
| 前端指令 | v-permission | UX 控制(防误操作、界面简洁)——可被绕过 |
| 后端校验 | Bind 包装层 HasPerm | 强制安全(403 拒绝)——唯一真值 |
定位认知
前端权限不是安全边界。绕过前端直接调接口的请求由后端 403 拦截。新增接口必须声明 gmeta permission(或评审确认留空=登录即可)。
菜单(type=0):控制"页面能否访问"(路由生成层面)
按钮(type=1 权限节点):控制"页面内操作能否看到"(指令层面)
getUser.permissions 下发权限码集合;菜单树不含按钮节点*:*:* 放行)