上一篇介绍了使用mybatis结合aop的方式实现数据权限控制,本次介绍使用mybatisPlus的拦截器功能实现数据权限控制,场景类似,不再赘述。
1、自定义注解
@Target( ElementType.METHOD )
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface DataScope {
/**
* 当前功能的authKey,根据authKey去查询当前用户的具体权限值
*/
String authKey() default "";
/**
* 需要加数据权限范围的表别名,单位权限
*/
String comTableName() default "sys_dept";
String comFieldName() default "dept_id";
}
2、自定义拦截器
public class DataScopeInterceptor implements InnerInterceptor {
/**
* {@link Executor#(MappedStatement, Object, RowBounds, ResultHandler, BoundSql)} 操作前置处理
* <p>
* 改改sql啥的
*
* @param executor Executor(可能是代理对象)
* @param ms MappedStatement
* @param parameter parameter
* @param rowBounds rowBounds
* @param resultHandler resultHandler
* @param boundSql boundSql
*/
@SneakyThrows
@Override
public void beforeQuery(Executor executor, MappedStatement ms, Object parameter, RowBounds rowBounds, ResultHandler resultHandler, BoundSql boundSql) throws SQLException {
// 获取当前用户id
Long userId = SecurityUtils.getUserId();
//获取当前用户所在部门id
Long deptId = SecurityUtils.getDeptId();
// 获取方法上的注解
DataScope dataScope = this.getDataScope(ms);
if (dataScope != null) {
// 获取注解中的authKey
String authKey = dataScope.authKey();
// 根据authKey和角色id查询当前用户在该功能下的权限值
//roleService.getDataValueByAuthKeyAndRoleId(authKey, role.getId());
//默认查询当前部门的数据,可按照自己需求调整
Integer dataValue =1;
if (dataValue != null) {
// 获取原始sql语句
String originalSql = boundSql.getSql();
// 根据不同的权限值,拼接不同的where条件
String whereSql = this.getWhereSqlByDataValue(dataValue, dataScope, userId,deptId);
if (StringUtils.isNotBlank(whereSql)) {
// 将拼接后的sql重新设置到boundSql中
String newSql = originalSql + whereSql;
Field sqlField = boundSql.getClass().getDeclaredField("sql");
sqlField.setAccessible(true);
sqlField.set(boundSql, newSql);
}
}
}
InnerInterceptor.super.beforeQuery(executor, ms, parameter, rowBounds, resultHandler, boundSql);
}
/**
* 根据不同的权限值,拼接不同的where条件
* @param dataValue 权限值
* @param dataScope 注解信息
* @param userId 用户id
* @return where条件语句
*/
private String getWhereSqlByDataValue(Integer dataValue, DataScope dataScope, Long userId,Long deptId) {
StringBuilder whereSql = new StringBuilder();
switch (dataValue) {
case 1: // 本单位权限
whereSql.append(" and ").append(dataScope.comTableName()).append(".").append(dataScope.comFieldName()).append(" = ").append(deptId);
break;
case 2: // 本单位及下级单位权限
// 获取当前用户所在部门及下级部门id列表
String deptSql="SELECT dept_id FROM sys_dept WHERE dept_id = {} or find_in_set( {} , ancestors )";
whereSql.append(" and ").append(dataScope.comTableName()).append(".").append(dataScope.comFieldName()).append(" in ").append("(").append(StrUtil.format(deptSql,deptId,deptId)).append(")");
break;
case 3: // 无权限
whereSql.append(" and 1 = 0"); // 拼接一个恒假条件,使得查询结果为空
break;
case 4: // 所有数据权限
break;
default:
break;
}
return whereSql.toString();
}
/**
* 获取方法上的注解信息
* @param mappedStatement 拦截器参数
* @return 注解对象或null
*/
private DataScope getDataScope(MappedStatement mappedStatement) {
String id = mappedStatement.getId();
String className = id.substring(0, id.lastIndexOf("."));
String methodName = id.substring(id.lastIndexOf(".") + 1);
Class<?> clazz = null;
try {
clazz = Class.forName(className);
} catch (ClassNotFoundException e) {
e.printStackTrace();
}
Method[] methods = clazz != null ? clazz.getDeclaredMethods() : null;
if (methods != null) {
for (Method method : methods) {
if (method.getName().equals(methodName)) {
return method.getAnnotation(DataScope.class);
}
}
}
return null;
}
}
3、注册拦截器
@Configuration
public class MybatisPlusConfig {
@Bean
public MybatisPlusInterceptor mybatisPlusInterceptor(){
MybatisPlusInterceptor interceptor=new MybatisPlusInterceptor();
interceptor.addInnerInterceptor(new DataScopeInterceptor());
return interceptor;
}
}
4、注解使用
该注解只能作用于mapper层的方法上,使用在其他地方无法生效
//默认查询部门下的用户列表
@DataScope
List<SysUserDto> queryAllUserList(@Param("po") SysUserDto sysUserDto);
对应的sql如下:
<select id="queryAllUserList" resultMap="SysUserMap">
select * from sys_user LEFT JOIN sys_dept ON sys_user.dept_id=sys_dept.dept_id where 1=1
</select>
以上就是通过mybatisPlus拦截器实现数据权限控制的基本使用方式。
没有回复内容