签入版本

This commit is contained in:
2026-10-08 17:50:29 +08:00
parent 809750b47e
commit e213a9b31d
444 changed files with 39366 additions and 37533 deletions
@@ -1,7 +1,7 @@
# 3.8 权限节点配置
:::tip 概述
权限节点用于控制用户能访问哪些接口。通过菜单管理界面配置,格式为 `sys:{模块名}:{操作}`。
权限节点用于控制用户能访问哪些接口。**菜单即权限**:菜单表的 `permission` 字段即权限编码,通过菜单管理界面配置,格式为 `sys:{模块名}:{操作}`;后端 `#[Permission]` 注解声明,`auth.jwt` 中间件统一校验。
:::
## Example 模块权限码
@@ -9,68 +9,93 @@
| 权限码 | 说明 | 对应接口 |
|--------|------|----------|
| `sys:example:page` | 案例演示分页列表 | `GET /api/example/page` |
| `sys:example:list` | 案例演示列表 | `GET /api/example/list` |
| `sys:example:detail` | 案例演示详情 | `GET /api/example/detail/{id}` |
| `sys:example:add` | 添加案例演示 | `POST /api/example/add` |
| `sys:example:update` | 修改案例演示 | `PUT /api/example/update` |
| `sys:example:delete` | 删除案例演示 | `DELETE /api/example/delete/:id` |
| `sys:example:delete` | 删除案例演示 | `DELETE /api/example/delete/{id}` |
| `sys:example:batchDelete` | 批量删除案例演示 | `DELETE /api/example/batchDelete` |
| `sys:example:import` | 导入案例演示 | `POST /api/example/import` |
| `sys:example:export` | 导出案例演示 | `GET /api/example/export` |
:::tip
控制器注解中声明的权限码(`#[Permission('sys:example:page', '示例分页')]`)必须与菜单管理中配置的 `permission` 字段**完全一致**,否则鉴权不通过。
:::
## 配置步骤
### 1. 添加目录节点
在系统菜单管理中添加一级目录:
在系统菜单管理中添加一级目录(项目已内置「开发工具」目录,id=189,可直接复用):
| 字段 | 值 |
|------|-----|
| 菜单名称 | 工具管理 |
| 菜单名称 | 开发工具 |
| 菜单类型 | 目录(type=0) |
| 路由地址 | /tool |
| 排序 | 60 |
| 排序 | 50 |
### 2. 添加菜单节点
### 2. 添加菜单节点(页面)
在目录下添加二级菜单:
在目录下添加二级菜单(可导航页面,代码生成器创建的路径即为此格式):
| 字段 | 值 |
|------|-----|
| 菜单名称 | 案例演示 |
| 菜单类型 | 菜单(type=1) |
| 路由地址 | /example |
| 菜单类型 | 菜单/页面(type=0) |
| 路由地址 | /tool/example |
| 组件路径 | tool/example/index |
| 权限标识 | sys:example:page |
| 排序 | 1 |
### 3. 添加按钮权限
### 3. 添加权限节点
在菜单下添加三级按钮权限:
在菜单下添加三级权限节点(type=1,`permission` 必填非空):
| 字段 | 值 | 权限标识 |
|------|-----|----------|
| 添加案例演示 | type=2 | sys:example:add |
| 修改案例演示 | type=2 | sys:example:update |
| 删除案例演示 | type=2 | sys:example:delete |
| 导入案例演示 | type=2 | sys:example:import |
| 导出案例演示 | type=2 | sys:example:export |
| 查看案例演示 | type=1 | sys:example:page |
| 添加案例演示 | type=1 | sys:example:add |
| 修改案例演示 | type=1 | sys:example:update |
| 删除案例演示 | type=1 | sys:example:delete |
| 导入案例演示 | type=1 | sys:example:import |
| 导出案例演示 | type=1 | sys:example:export |
### 4. 分配角色权限
在角色管理中,为角色勾选新增的权限节点。
在角色管理中,为角色勾选新增的权限节点(角色 → 菜单多对多,存于 `role_menu` 表)。
## 菜单类型说明
| type | 说明 | 前端行为 |
|------|------|----------|
| 0 | 目录 | 渲染为侧边栏分组 |
| 1 | 菜单 | 渲染为可点击的菜单项,对应一个页面 |
| 2 | 按钮 | 不渲染,仅用于权限校验 |
| 0 | 菜单/目录(可导航) | 目录渲染为侧边栏分组,页面渲染为菜单项(需填 `component`) |
| 1 | 权限节点 | 不渲染,仅用于接口鉴权(`permission` 必填非空) |
## 权限校验流程
```text
1. 用户登录 → 获取用户角色
2. 角色关联菜单 → 获取权限节点列表
3. 请求接口 → AuthMiddleware 读取 #[Permission] 注解
1. 用户登录 → 获取用户角色(user_role 表)
2. 角色关联菜单 → 获取权限节点列表(role_menu 表,缓存于 Redis)
3. 请求接口 → auth.jwt 中间件读取控制器方法的 #[Permission] 注解(反射)
4. 检查权限码是否在用户权限列表中
5. 超级管理员(uid=1)跳过校验,直接放行
```
├─ 在 → 放行,进入 tenant / demo / log.operation 中间件
├─ 不在 → 返回 {"code":403,"ok":false,"msg":"无访问权限"}
└─ 超级管理员(用户 ID=1)→ 跳过校验,直接放行
5. 菜单/角色菜单数据变更时,Observer 自动清除相关权限缓存
```
:::tip 两级校验
- **后端**:`#[Permission]` 注解 + `auth.jwt` 中间件(接口级,兜底);
- **前端**:`v-perm` 按钮指令(体验层,隐藏无权按钮)。
前端隐藏不等于安全——后端注解校验才是权限的最终防线。详见 [5.4 权限管理(RBAC)](/zh/core/rbac.html)。
:::
## 常见问题
| 现象 | 原因 | 处理 |
|------|------|------|
| 超管正常、普通角色 403 | 角色未分配该权限节点 | 角色管理勾选对应菜单/按钮 |
| 改了权限不生效 | 权限缓存未失效 | 重新保存角色菜单(`RoleMenuObserver` 自动清除权限缓存),或重新登录 |
| 注解写了仍 403 | 权限码与菜单 `permission` 不一致 | 逐字符比对(注意大小写与冒号) |
| 无 `#[Permission]` 的接口被拦截 | 接口放错位置 | 确认是否应为公开路由,移至中间件组外 |