mybatis拦截器实现数据权限
数据权限拦截器:
@Data
@NoArgsConstructor
@AllArgsConstructor
@ToString(callSuper = true)
@EqualsAndHashCode(callSuper = true)
public class MyDataPermissionInterceptor extends JsqlParserSupport implements InnerInterceptor {
/**
* 数据权限处理器
*/
private MyDataPermissionHandler dataPermissionHandler;
@Override
public void beforeQuery(Executor executor, MappedStatement ms, Object parameter, RowBounds rowBounds, ResultHandler resultHandler, BoundSql boundSql) throws SQLException {
if (InterceptorIgnoreHelper.willIgnoreDataPermission(ms.getId())) {
return;
}
PluginUtils.MPBoundSql mpBs = PluginUtils.mpBoundSql(boundSql);
mpBs.sql(this.parserSingle(mpBs.sql(), ms.getId()));
}
@Override
protected void processSelect(Select select, int index, String sql, Object obj) {
SelectBody selectBody = select.getSelectBody();
if (selectBody instanceof PlainSelect) {
this.setWhere((PlainSelect) selectBody, (String) obj);
} else if (selectBody instanceof SetOperationList) {
SetOperationList setOperationList = (SetOperationList) selectBody;
List<SelectBody> selectBodyList = setOperationList.getSelects();
selectBodyList.forEach(s -> this.setWhere((PlainSelect) s, (String) obj));
}
}
/**
* 设置 where 条件
*
* @param plainSelect 查询对象
* @param whereSegment 查询条件片段
*/
private void setWhere(PlainSelect plainSelect, String whereSegment) {
Expression sqlSegment = this.dataPermissionHandler.getSqlSegment(plainSelect, whereSegment);
if (null != sqlSegment) {
plainSelect.setWhere(sqlSegment);
}
}
}
具体业务实现拼接
@Slf4j
public class MyDataPermissionHandler {
private UserService userService;
/**
* 获取数据权限 SQL 片段
*
* @param plainSelect 查询对象
* @param whereSegment 查询条件片段
* @return JSqlParser 条件表达式
*/
@SneakyThrows(Exception.class)
public Expression getSqlSegment(PlainSelect plainSelect, String whereSegment) {
userService = SpringUtils.getBean(UserService.class);
// 待执行 SQL Where 条件表达式
Expression where = plainSelect.getWhere();
if (where == null) {
where = new HexValue(" 1 = 1 ");
}
log.info("开始进行权限过滤,dataFilterMetaData:{} , where: {},mappedStatementId: {}", 111, where, whereSegment);
//获取mapper名称
String className = whereSegment.substring(0, whereSegment.lastIndexOf("."));
//获取方法名
String methodName = whereSegment.substring(whereSegment.lastIndexOf(".") + 1);
Table fromItem = (Table) plainSelect.getFromItem();
// 有别名用别名,无别名用表名,防止字段冲突报错
Alias fromItemAlias = fromItem.getAlias();
String mainTableName = fromItemAlias == null ? fromItem.getName() : fromItemAlias.getName();
//获取当前mapper 的方法
Method[] methods = Class.forName(className).getMethods();
for (Method m : methods) {
if (Objects.equals(m.getName(), methodName)) {
UserDataPermission annotation = m.getAnnotation(UserDataPermission.class);
if (annotation == null) {
return where;
}
Long userId = BaseContextHandler.getUserId();
User currentUser = userService.getById(userId);
DataScopeType dsType = currentUser.getDsType();
//有注解,需要进行数据权限拦截
switch (dsType) {
// 查看全部
case ALL:
return where;
// 查看自己的数据
case THIS_LEVEL:
// = 表达式
// dept_id = deptId
EqualsTo usesEqualsTo = new EqualsTo();
usesEqualsTo.setLeftExpression(new Column(mainTableName+".create_user"));
usesEqualsTo.setRightExpression(new LongValue(currentUser.getId()));
return new AndExpression(where, usesEqualsTo);
// 查看本人所在职务以及下属职务
case THIS_LEVEL_CHILDREN:
//create_user in (····)
// 创建IN 表达式
// 创建IN范围的元素集合
Long stationId = currentUser.getStationId();
List<Long> ids = userService.getUserAndChildJob(stationId);
log.info("本级及子级用户id:{}",ids);
// 把集合转变为JSQLParser需要的元素列表
ItemsList itemsList = new ExpressionList(ids.stream().map(LongValue::new).collect(Collectors.toList()));
InExpression inExpression = new InExpression(new Column(mainTableName+".create_user"), itemsList);
return new AndExpression(where, inExpression);
// 查看当前部门的数据
case THIS_DEPARTMENT:
// dept_id = dept_id
EqualsTo selfEqualsTo = new EqualsTo();
selfEqualsTo.setLeftExpression(new Column(mainTableName+".dept_id"));
selfEqualsTo.setRightExpression(new LongValue(currentUser.getOrgId()));
return new AndExpression(where, selfEqualsTo);
//查看当前部门及下属部门
case THIS_DEPARTMENT_CHILDREN:
// 创建IN 表达式
// 创建IN范围的元素集合
Set<Long> deptIds = userService.getDeptIds(currentUser.getOrgId());
log.info("本部门及子部门部门id:{}",deptIds);
// 把集合转变为JSQLParser需要的元素列表
ItemsList deptList = new ExpressionList(deptIds.stream().map(LongValue::new).collect(Collectors.toList()));
InExpression inExpressiondept = new InExpression(new Column(mainTableName+".dept_id"), deptList);
return new AndExpression(where, inExpressiondept);
//本地区
case THIS_REGION:
// region_id = dept_id
EqualsTo regionEqualsTo = new EqualsTo();
log.info("查询本地区:{}",currentUser.getAdressId());
regionEqualsTo.setLeftExpression(new Column(mainTableName+".region_id"));
regionEqualsTo.setRightExpression(new LongValue(currentUser.getAdressId()));
return new AndExpression(where, regionEqualsTo);
case ASSIGN_USER:
case ASSIGN_DEPARTMENT:
case ASSIGN_REGION:
default:
break;
}
}
}
//说明无权查看,
where = new HexValue(" 1 = 2 ");
return where;
}
}
自定义注解
@Target({ElementType.METHOD, ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
public @interface UserDataPermission {
}
完成拦截器注册
/**
* @program: crm_backend
* @description: mybatisplusconfig
* @author: JiaChaoYang
* @create: 2022-07-21 17:07
**/
@Configuration
public class MyBatisPlusConfig {
/**
* @Description 分页插件,一缓和二缓遵循mybatis的规则,
* @Params []
* @Return com.baomidou.mybatisplus.extension.plugins.MybatisPlusInterceptor
* @Author JiaChaoYang
* @Date 2022/7/21 17:10
*/
@Bean
public MybatisPlusInterceptor mybatisPlusInterceptor() {
MybatisPlusInterceptor interceptor = new MybatisPlusInterceptor();
// 添加数据权限插件
MyDataPermissionInterceptor dataPermissionInterceptor = new MyDataPermissionInterceptor();
// 添加自定义的数据权限处理器
dataPermissionInterceptor.setDataPermissionHandler(new MyDataPermissionHandler());
interceptor.addInnerInterceptor(dataPermissionInterceptor);
interceptor.addInnerInterceptor(new PaginationInnerInterceptor(DbType.MYSQL));
return interceptor;
}
}
如何使用:
在mapper层添加注解即可
@UserDataPermission
List<CustomerAllVO> selectAllCustomerPage(IPage<CustomerAllVO> page, @Param("customerName")String customerName ,
@Param("customerCreditCode")String customerCreditCode,
@Param("teamUserId")Integer teamUserId);