ps:本文所使用的若依是前后端分离的v3.6.0版本。
1、建表
建立业务表的时候,需要在表中添加user_id和dept_id两个字段。(字段一定要一样,下文能体现)
user_id:表中该条记录的创建人id
dept_id:表中该条记录的创建人的部门id
建表SQL:
CREATE TABLE `t_warehouse_info` (
`id` bigint(20) NOT NULL AUTO_INCREMENT COMMENT '主键ID',
`user_id` bigint(20) DEFAULT NULL COMMENT '用户ID',
`dept_id` bigint(20) DEFAULT NULL COMMENT '部门ID',
`warehouse_code` varchar(255) DEFAULT NULL COMMENT '地址编码',
`sort` bigint(20) DEFAULT '1' COMMENT '排序',
`video_original_name` varchar(500) DEFAULT NULL COMMENT '源视频名',
`video_name` varchar(500) DEFAULT NULL COMMENT '视频名字',
`video_url` varchar(500) DEFAULT NULL COMMENT '视频具体地址',
`original_file_name` varchar(500) DEFAULT NULL COMMENT '源文件名(图片、pdf)',
`file_name` varchar(500) DEFAULT NULL COMMENT '文件名(图片、pdf)',
`file_url` varchar(500) DEFAULT NULL COMMENT '文件具体地址(图片、pdf)',
`create_time` datetime DEFAULT NULL COMMENT '创建时间',
`update_time` datetime DEFAULT NULL COMMENT '更新时间',
`remark` varchar(500) DEFAULT NULL COMMENT '备注',
PRIMARY KEY (`id`) USING BTREE
) ENGINE=InnoDB AUTO_INCREMENT=8 DEFAULT CHARSET=utf8mb4 ROW_FORMAT=DYNAMIC COMMENT='整体库房介绍';
2、生成代码
本地运行若依管理平台,打开代码生成页面。
点击导入表
选择导入刚刚创建的业务表
点击生成代码
3、设置用户权限
例如本人用超级用户给自己创建了一个用户,用户角色的信息如下:
本人的角色权限是部门及以下的权限
4、代码修改
生成的代码我们是不能直接使用的。需要做一些修改。
首先在controller类的插入记录接口中,为实体类插入用户id和部门id
其次在xml文件中,为select的sql添加 表别名 和 ${params.dataScope}
最后在service的实现类的列表查询方法上添加 注解
@DataScope(deptAlias = "d", userAlias = "d")
注意发现:
deptAlias = "d", userAlias = "d"
中的d就是表的别名。
5、原理分析
ctrl+左键点击我们发现他是一个自定义注解
在数据切面类中,获取了当前用户信息,并且将注解中的表别名一并传入了dataScopeFilter方法中。
我们在点击进入到dataScopeFilter方法中。
瞬间明白了,通过if判断当前用户的权限范围,配合注解中的表别名,生成不同权限的sql语句。
最后将sql放到业务实体类继承的BaseEntity类的params字段中。
xml文件中的${params.dataScope}就是对应了BaseEntity类中的params字段。
/**
*
* @param joinPoint 切点
* @param user 当前用户
* @param deptAlias 部门表别名
* @param userAlias 用户表别名
*/
public static void dataScopeFilter(JoinPoint joinPoint, SysUser user, String deptAlias, String userAlias)
{
StringBuilder sqlString = new StringBuilder();
for (SysRole role : user.getRoles())
{
// 获取当前用户的数据权限范围
String dataScope = role.getDataScope();
if (DATA_SCOPE_ALL.equals(dataScope))
{
/** 全部数据权限 1 */
sqlString = new StringBuilder();
break;
}
else if (DATA_SCOPE_CUSTOM.equals(dataScope))
{
/** 自定数据权限 2 */
sqlString.append(StringUtils.format(
" OR {}.dept_id IN ( SELECT dept_id FROM sys_role_dept WHERE role_id = {} ) ", deptAlias,
role.getRoleId()));
}
else if (DATA_SCOPE_DEPT.equals(dataScope))
{
/** 部门数据权限 3 */
sqlString.append(StringUtils.format(" OR {}.dept_id = {} ", deptAlias, user.getDeptId()));
}
else if (DATA_SCOPE_DEPT_AND_CHILD.equals(dataScope))
{
/** 部门及以下数据权限 4 */
sqlString.append(StringUtils.format(
" OR {}.dept_id IN ( SELECT dept_id FROM sys_dept WHERE dept_id = {} or find_in_set( {} , ancestors ) )",
deptAlias, user.getDeptId(), user.getDeptId()));
}
else if (DATA_SCOPE_SELF.equals(dataScope))
{
if (StringUtils.isNotBlank(userAlias))
{
/** 仅本人数据权限 5 */
sqlString.append(StringUtils.format(" OR {}.user_id = {} ", userAlias, user.getUserId()));
}
else
{
// 数据权限为仅本人且没有userAlias别名不查询任何数据
sqlString.append(" OR 1=0 ");
}
}
}
if (StringUtils.isNotBlank(sqlString.toString()))
{
Object params = joinPoint.getArgs()[0];
if (StringUtils.isNotNull(params) && params instanceof BaseEntity)
{
BaseEntity baseEntity = (BaseEntity) params;
baseEntity.getParams().put(DATA_SCOPE, " AND (" + sqlString.substring(4) + ")");
}
}
}
这里权限范围值是存在了dataScope字段中。
通过dataScope字段对比
/**
* 全部数据权限
*/
public static final String DATA_SCOPE_ALL = "1";
/**
* 自定数据权限
*/
public static final String DATA_SCOPE_CUSTOM = "2";
/**
* 部门数据权限
*/
public static final String DATA_SCOPE_DEPT = "3";
/**
* 部门及以下数据权限
*/
public static final String DATA_SCOPE_DEPT_AND_CHILD = "4";
/**
* 仅本人数据权限
*/
public static final String DATA_SCOPE_SELF = "5";
/**
* 数据权限过滤关键字
*/
public static final String DATA_SCOPE = "dataScope";
例如本人的权限范围是:本部门及以下的权限。则生成的sql语句是:
OR u.dept_id IN ( SELECT dept_id FROM sys_dept WHERE dept_id = {当前登录用户部门id} or find_in_set( {当前登录用户部门id} , ancestors ) )
最后存在BaseEntity类的params字段中。
/**
* Entity基类
*
* @author ruoyi
*/
public class BaseEntity implements Serializable {
private static final long serialVersionUID = 1L;
/** 搜索值 */
private String searchValue;
/** 创建者 */
private String createBy;
/** 创建时间 */
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
@Excel(name = "时间", dateFormat = "yyyy-MM-dd HH:mm:ss",sort = 100,width = 28)
private Date createTime;
/** 更新者 */
private String updateBy;
/** 更新时间 */
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
private Date updateTime;
/** 备注 */
private String remark;
/** 请求参数 */
private Map<String, Object> params;
}
6、最终请求执行的SQL 语句
14:59:24.942 [http-nio-8080-exec-21] DEBUG c.r.c.m.W.selectWarehouseInfoList - [debug,137] - ==> Preparing: select id, user_id, dept_id, warehouse_code, sort, video_original_name, video_name, video_url, original_file_name, file_name, file_url, create_time, update_time, remark from t_warehouse_info d WHERE (d.dept_id IN ( SELECT dept_id FROM sys_dept WHERE dept_id = 204 or find_in_set( 204 , ancestors ) )) order by sort
# 提取Sql
select id, user_id, dept_id, warehouse_code, sort, video_original_name, video_name, video_url, original_file_name, file_name, file_url, create_time, update_time, remark from t_warehouse_info d WHERE (d.dept_id IN ( SELECT dept_id FROM sys_dept WHERE dept_id = 204 or find_in_set( 204 , ancestors ) )) order by sort