签入版本
This commit is contained in:
@@ -0,0 +1,68 @@
|
||||
# 9.7 权限控制
|
||||
|
||||
:::tip 概述
|
||||
前端权限是按钮级 UX 控制:directives/permission.ts 按 getUser 返回的 permissions 数组控制元素显隐;超管通配权限 `*:*:*` 直接放行。后端接口级校验是强制层(403),前端指令只是体验层。
|
||||
:::
|
||||
|
||||
## 权限数据流
|
||||
|
||||
```text
|
||||
登录 → GetInfo(/api/index/getUser)
|
||||
→ userInfo.permissions(后端 LoadIdentity 的 Perms)
|
||||
超管 = ["*:*:*"](通配)
|
||||
→ store 缓存 → 指令消费
|
||||
```
|
||||
|
||||
后端 Perms 来源:role_menu → menu(type=1 且 status=0 且 hide=0)的 permission 去重集合(详见 [5.4 权限管理(RBAC)](../core/rbac))。
|
||||
|
||||
## 指令用法(directives/permission.ts)
|
||||
|
||||
```text
|
||||
按钮级控制(语义示意):
|
||||
<el-button v-permission="'sys:user:add'">新增</el-button>
|
||||
|
||||
指令逻辑:
|
||||
permissions 含 "*:*:*" → 放行(超管)
|
||||
permissions 含传入权限码 → 放行
|
||||
否则 → 移除元素(v-if 等效)
|
||||
```
|
||||
|
||||
## 前后端权限对照(联调要点)
|
||||
|
||||
```text
|
||||
后端 gmeta permission:"sys:user:add"
|
||||
↔ 前端指令 v-permission="'sys:user:add'"
|
||||
↔ 菜单权限节点 permission=sys:user:add
|
||||
↔ 角色已勾选该节点
|
||||
|
||||
四处必须一致——不一致的表现:
|
||||
前端可见按钮但后端 403 → 节点存在但角色未勾选(或身份缓存旧)
|
||||
前端按钮消失但后端有权限 → permissions 缓存旧 / 指令码拼错
|
||||
```
|
||||
|
||||
## 双重校验的定位
|
||||
|
||||
| 层 | 位置 | 性质 |
|
||||
|----|------|------|
|
||||
| 前端指令 | v-permission | UX 控制(防误操作、界面简洁)——**可被绕过** |
|
||||
| 后端校验 | Bind 包装层 HasPerm | 强制安全(403 拒绝)——唯一真值 |
|
||||
|
||||
::: warning 定位认知
|
||||
前端权限不是安全边界。绕过前端直接调接口的请求由后端 403 拦截。新增接口**必须**声明 gmeta permission(或评审确认留空=登录即可)。
|
||||
:::
|
||||
|
||||
## 菜单与按钮的分层
|
||||
|
||||
```text
|
||||
菜单(type=0):控制"页面能否访问"(路由生成层面)
|
||||
按钮(type=1 权限节点):控制"页面内操作能否看到"(指令层面)
|
||||
getUser.permissions 下发权限码集合;菜单树不含按钮节点
|
||||
```
|
||||
|
||||
## 开发规约
|
||||
|
||||
+ 页面按钮逐个对齐 gmeta permission 码(复制粘贴防拼错)
|
||||
+ 新增权限码流程:gmeta 声明 → 菜单建节点 → 角色勾选 → 指令引用
|
||||
+ 不要发明前端私有权限码(必须与后端节点一致才有意义)
|
||||
+ 超管测试:admin 账号应看到全部按钮(`*:*:*` 放行)
|
||||
+ 权限变更后重新登录验证(身份缓存 300s;前端 GetInfo 在登录/刷新时拉取)
|
||||
Reference in New Issue
Block a user