Become a sponsor

后端代码中的 permission_required = ("sys:example:page",) 定义了接口所需的权限字符串,但权限节点本身需要在数据库中配置,才能在「菜单管理」中分配给角色。
sys:{module}:{action}| 部分 | 说明 | 示例 |
|---|---|---|
sys | 系统前缀(固定) | sys |
module | 模块名(小写) | example |
action | 操作名 | page / add / update / delete |
| 权限字符串 | 说明 | HTTP 方法 | 路径 |
|---|---|---|---|
sys:example:page | 分页查询 | GET | /example/page |
sys:example:detail | 详情查询 | GET | /example/detail/{id} |
sys:example:list | 列表查询 | GET | /example/list |
sys:example:add | 新增案例 | POST | /example/add |
sys:example:update | 更新案例 | PUT | /example/update |
sys:example:delete | 删除案例 | DELETE | /example/delete/{id} |
sys:example:status | 状态变更 | PUT | /example/status |
用户请求 → check_login(JWT 校验) → PermissionRequired(权限校验)
├── 用户 ID = 1(admin)→ 跳过权限校验,直接放行
└── 其他用户 → 查询角色权限列表 → 匹配权限字符串 → 放行 / 拒绝class PermissionRequired(PermissionRequiredMixin):
def has_permission(self):
permissions = self.get_permission_required()
user_id = get_user_id(self.request)
# 超级管理员自动放行
if user_id and user_id != 1:
from application.menu import services
permission_list = services.get_user_permissions(user_id)
for permission in permissions:
if permission not in permission_list:
return False
return True
def handle_no_permission(self):
return R.failed("暂无操作权限", 401)get_user_permissions(user_id) 返回用户拥有的所有权限节点登录管理后台,进入「系统管理 -> 菜单管理」:
| 字段 | 值 |
|---|---|
| 菜单类型 | 权限 |
| 权限标识 | sys:example:page |
| 菜单名称 | 案例查询 |
为每个接口重复上述步骤,添加全部权限节点。
查询类权限(page、detail、list)通常合并为一个节点 sys:example:list,减少配置工作量。写操作(add、update、delete、status)建议独立配置,便于细粒度控制。
权限节点创建并启用后,需将其分配给角色,用户才能通过角色继承相应权限。
操作路径:「系统管理 -> 角色管理」
注意:权限分配后,拥有该角色的用户需重新登录或刷新页面才能获取最新权限。
前端使用 v-perm 指令控制按钮显示:
<!-- 新增按钮 -->
<el-button v-perm="['sys:example:add']">添加案例</el-button>
<!-- 批量删除按钮 -->
<el-button v-perm="['sys:example:batchDelete']">批量删除</el-button>操作栏按钮使用 auth 属性:
{
label: '编辑',
icon: 'Edit',
onClick: handleEdit.bind(null, record),
auth: ['sys:example:update'],
}如果需要通过 SQL 直接插入权限节点(如初始化脚本),参考以下语句:
-- 假设案例管理菜单 ID 为 200
INSERT INTO django_menu (name, parent_id, path, component, perms, type, icon, sort, create_time, is_delete)
VALUES
('案例查询', 200, NULL, NULL, 'sys:example:page', '1', NULL, 0, NOW(), 0),
('案例新增', 200, NULL, NULL, 'sys:example:add', '1', NULL, 0, NOW(), 0),
('案例编辑', 200, NULL, NULL, 'sys:example:update', '1', NULL, 0, NOW(), 0),
('案例删除', 200, NULL, NULL, 'sys:example:delete', '1', NULL, 0, NOW(), 0),
('案例状态', 200, NULL, NULL, 'sys:example:status', '1', NULL, 0, NOW(), 0);其中 type='1' 表示权限类型节点(非菜单)。
permission_required 完全一致1(权限),不是 0(菜单)权限节点是菜单的子节点(type=1),命名规范为 sys:{模块}:{操作}。后端通过 PermissionRequired 混入类校验,前端通过 v-perm 指令控制按钮显示。admin 用户(ID=1)自动跳过权限校验,查询权限可适当合并,写操作权限建议独立以实现细粒度控制。