若依框架中权限字符(perms)的作用
让我用一个更简单的例子来解释权限字符(perms)的作用:
场景举例:导出功能
假设系统中有3个页面都需要导出功能:
- 用户管理页面
- 订单管理页面
- 商品管理页面
方案1:不使用perms(传统方式)
- 在菜单表中需要创建3个按钮记录:
sql
Apply to SysMenu.java
-- 用户管理的导出按钮
INSERT INTO sys_menu (menu_id, menu_name, menu_type, parent_id)
VALUES (101, '导出用户', 'F', 100);
-- 订单管理的导出按钮
INSERT INTO sys_menu (menu_id, menu_name, menu_type, parent_id)
VALUES (201, '导出订单', 'F', 200);
-- 商品管理的导出按钮
INSERT INTO sys_menu (menu_id, menu_name, menu_type, parent_id)
VALUES (301, '导出商品', 'F', 300);
- 如果管理员需要导出权限,需要在角色-菜单关联表中插入3条记录:
sql
Apply to SysMenu.java
INSERT INTO sys_role_menu (role_id, menu_id) VALUES (1, 101); -- 用户导出
INSERT INTO sys_role_menu (role_id, menu_id) VALUES (1, 201); -- 订单导出
INSERT INTO sys_role_menu (role_id, menu_id) VALUES (1, 301); -- 商品导出
方案2:使用perms(若依方式)
- 在菜单表中创建按钮时,使用相同的权限字符:
sql
Apply to SysMenu.java
-- 用户管理的导出按钮
INSERT INTO sys_menu (menu_id, menu_name, menu_type, parent_id, perms)
VALUES (101, '导出用户', 'F', 100, 'system:export');
-- 订单管理的导出按钮
INSERT INTO sys_menu (menu_id, menu_name, menu_type, parent_id, perms)
VALUES (201, '导出订单', 'F', 200, 'system:export');
-- 商品管理的导出按钮
INSERT INTO sys_menu (menu_id, menu_name, menu_type, parent_id, perms)
VALUES (301, '导出商品', 'F', 300, 'system:export');
- 管理员只需要被授予一次导出权限:
sql
Apply to SysMenu.java
INSERT INTO sys_role_permission (role_id, permission)
VALUES (1, 'system:export');
主要区别
- 权限管理更简单
- 不使用perms:每新增一个导出功能,都需要给角色重新授权
- 使用perms:只要角色有system:export权限,就能使用所有导出功能
- 代码实现更统一
- 不使用perms:每个导出接口都需要单独写权限校验
- 使用perms:所有导出接口可以用同一个权限注解@PreAuthorize("@ss.hasPermi('system:export')")
- 维护成本更低
- 不使用perms:新增导出功能时,需要修改菜单表和角色授权
- 使用perms:新增导出功能时,只需添加菜单记录,无需修改角色授权
实际应用示例
java
Apply to SysMenu.java
// 用户导出接口
@PreAuthorize("@ss.hasPermi('system:export')")
public void exportUsers() {
// 导出用户逻辑
}
// 订单导出接口
@PreAuthorize("@ss.hasPermi('system:export')")
public void exportOrders() {
// 导出订单逻辑
}
// 商品导出接口
@PreAuthorize("@ss.hasPermi('system:export')")
public void exportProducts() {
// 导出商品逻辑
}
这样,只要用户有system:export权限,就能使用所有导出功能,不需要为每个导出功能单独授权。这就是权限复用的核心思想。
所以只是这么用吗这个权限字符?为什么要所有导出都能导出,如果我只允许订单导出怎么办?
啊,这是个很好的问题!让我重新解释一下权限字符(perms)的更完整用法:
1. 权限字符的层级设计
权限字符通常采用"模块:操作"的格式,可以设计多个层级:
java
Apply to SysMenu.java
// 基础权限
system:export // 所有导出权限
order:export // 订单导出权限
user:export // 用户导出权限
// 更细粒度的权限
order:export:detail // 订单详情导出
order:export:summary // 订单汇总导出
2. 实际应用场景
场景1:只允许订单导出
java
Apply to SysMenu.java
// 订单导出接口
@PreAuthorize("@ss.hasPermi('order:export')")
public void exportOrders() {
// 导出订单逻辑
}
// 用户导出接口
@PreAuthorize("@ss.hasPermi('user:export')")
public void exportUsers() {
// 导出用户逻辑
}
数据库配置:
sql
Apply to SysMenu.java
-- 订单导出按钮
INSERT INTO sys_menu (menu_id, menu_name, menu_type, parent_id, perms)
VALUES (201, '导出订单', 'F', 200, 'order:export');
-- 用户导出按钮
INSERT INTO sys_menu (menu_id, menu_name, menu_type, parent_id, perms)
VALUES (101, '导出用户', 'F', 100, 'user:export');
-- 角色权限配置
INSERT INTO sys_role_permission (role_id, permission)
VALUES (1, 'order:export'); -- 只给订单导出权限
场景2:不同级别的导出权限
java
Apply to SysMenu.java
// 订单详情导出
@PreAuthorize("@ss.hasPermi('order:export:detail')")
public void exportOrderDetail() {
// 导出订单详情
}
// 订单汇总导出
@PreAuthorize("@ss.hasPermi('order:export:summary')")
public void exportOrderSummary() {
// 导出订单汇总
}
3. 权限字符的优势
- 灵活的权限控制
- 可以精确控制到具体功能
- 可以设置不同级别的权限
- 权限组合
java
Apply to SysMenu.java
// 需要同时具备多个权限
@PreAuthorize("@ss.hasPermi('order:export') and @ss.hasPermi('order:view')")
public void exportOrders() {
// 导出订单逻辑
}
- 权限继承
java
Apply to SysMenu.java
// 检查是否有订单模块的任何权限
@PreAuthorize("@ss.hasPermi('order:*')")
public void orderOperation() {
// 订单相关操作
}
4. 实际使用建议
- 权限命名规范
text
Apply to SysMenu.java
模块:操作:子操作
例如:
order:export:detail // 订单详情导出
order:export:summary // 订单汇总导出
user:add // 用户添加
user:edit // 用户编辑
- 权限粒度控制
java
Apply to SysMenu.java
// 粗粒度权限
@PreAuthorize("@ss.hasPermi('order:*')")
// 细粒度权限
@PreAuthorize("@ss.hasPermi('order:export:detail')")
- 权限组合使用
java
Apply to SysMenu.java
// 需要同时具备多个权限
@PreAuthorize("@ss.hasPermi('order:export') and @ss.hasPermi('order:view')")
// 具备任一权限即可
@PreAuthorize("@ss.hasPermi('order:export') or @ss.hasPermi('order:view')")
所以,权限字符(perms)不仅可以实现权限复用,更重要的是可以实现精确的权限控制。你可以根据业务需求,设计不同粒度的权限控制,而不是简单地让所有导出功能共享同一个权限。
所以,它这个权限字符设计在菜单表更合理是吧,能设计在角色表中吗?就是这个perms
是的,权限字符(perms)设计在菜单表中更合理,原因如下:
1. 菜单表设计更合理的原因
- 与菜单按钮一一对应
sql
Apply to SysMenu.java
-- 菜单表
CREATE TABLE sys_menu (
menu_id BIGINT PRIMARY KEY,
menu_name VARCHAR(50),
menu_type CHAR(1), -- M目录 C菜单 F按钮
perms VARCHAR(100) -- 权限字符
);
-- 示例数据
INSERT INTO sys_menu VALUES
(101, '导出用户', 'F', 'user:export'),
(102, '编辑用户', 'F', 'user:edit'),
(201, '导出订单', 'F', 'order:export');
- 权限与UI元素绑定
- 每个按钮/菜单项都有对应的权限字符
- 前端可以根据权限字符控制按钮的显示/隐藏
- 后端可以根据权限字符控制接口的访问
- 维护更方便
- 添加新功能时,直接在菜单表中配置权限
- 权限与功能点一一对应,便于管理
2. 为什么不适合放在角色表中
- 数据冗余
sql
Apply to SysMenu.java
-- 角色表(不推荐)
CREATE TABLE sys_role (
role_id BIGINT PRIMARY KEY,
role_name VARCHAR(50),
perms VARCHAR(1000) -- 存储所有权限字符,会导致数据冗余
);
- 维护困难
- 需要手动维护权限字符串
- 容易出错
- 难以追踪权限来源
- 扩展性差
- 新增权限需要修改角色表
- 难以实现细粒度的权限控制
3. 正确的设计方式
sql
Apply to SysMenu.java
-- 1. 菜单表(包含权限字符)
CREATE TABLE sys_menu (
menu_id BIGINT PRIMARY KEY,
menu_name VARCHAR(50),
menu_type CHAR(1),
perms VARCHAR(100)
);
-- 2. 角色表
CREATE TABLE sys_role (
role_id BIGINT PRIMARY KEY,
role_name VARCHAR(50)
);
-- 3. 角色-菜单关联表
CREATE TABLE sys_role_menu (
role_id BIGINT,
menu_id BIGINT
);
4. 实际使用示例
java
Apply to SysMenu.java
// 1. 菜单配置
INSERT INTO sys_menu VALUES
(101, '导出用户', 'F', 'user:export'),
(102, '编辑用户', 'F', 'user:edit');
// 2. 角色配置
INSERT INTO sys_role VALUES
(1, '管理员'),
(2, '普通用户');
// 3. 角色-菜单关联
INSERT INTO sys_role_menu VALUES
(1, 101), -- 管理员可以导出用户
(1, 102), -- 管理员可以编辑用户
(2, 101); -- 普通用户只能导出用户
5. 权限控制实现
java
Apply to SysMenu.java
// 1. 前端控制
<button v-if="hasPermi('user:export')">导出用户</button>
<button v-if="hasPermi('user:edit')">编辑用户</button>
// 2. 后端控制
@PreAuthorize("@ss.hasPermi('user:export')")
public void exportUsers() {
// 导出用户逻辑
}
@PreAuthorize("@ss.hasPermi('user:edit')")
public void editUser() {
// 编辑用户逻辑
}
6. 优势总结
- 结构清晰
- 权限与功能点一一对应
- 便于管理和维护
- 扩展性好
- 易于添加新权限
- 支持细粒度控制
- 使用方便
- 前端可以直接根据权限控制显示
- 后端可以直接使用注解控制访问
- 维护简单
- 权限变更只需修改菜单表
- 角色权限通过关联表管理
所以,权限字符(perms)设计在菜单表中是最合理的选择,它能够更好地支持权限管理系统的实现和维护。