All Downloads are FREE. Search and download functionalities are using the official Maven repository.

matrix.boot.jdbc.orm.mybatis.handler.CustomDataPermissionHandler Maven / Gradle / Ivy

package matrix.boot.jdbc.orm.mybatis.handler;

import matrix.boot.based.dto.DataPermissionDto;
import matrix.boot.based.enums.DataPermissionOperateEnum;
import matrix.boot.common.exception.ServiceException;
import matrix.boot.jdbc.orm.mybatis.intercept.DataPermissionMybatisPlusInterceptor;
import net.sf.jsqlparser.expression.*;
import net.sf.jsqlparser.expression.operators.relational.*;
import net.sf.jsqlparser.parser.CCJSqlParserUtil;
import net.sf.jsqlparser.schema.Column;
import net.sf.jsqlparser.statement.select.PlainSelect;
import net.sf.jsqlparser.util.cnfexpression.MultiAndExpression;
import net.sf.jsqlparser.util.cnfexpression.MultiOrExpression;
import org.springframework.util.CollectionUtils;

import java.util.*;
import java.util.concurrent.atomic.AtomicInteger;

/**
 * 数据权限拦截处理器
 *
 * @author wangcheng
 * date 2022/4/12
 */
public class CustomDataPermissionHandler {

    /**
     * 处理数据权限
     *
     * @param allPlainSelects       所以选择器(包含子查询)
     * @param unionPlainSelects     union选择器(只有最外层union的where)
     * @param aliasMap              别名字典项
     * @param normalDataPermission  普通数据权限
     * @param specialDataPermission 特殊数据权限
     */
    public void processDataPermission(List allPlainSelects, List unionPlainSelects,
                                      Map aliasMap,
                                      List> normalDataPermission, List specialDataPermission) {
        if (CollectionUtils.isEmpty(allPlainSelects) && CollectionUtils.isEmpty(unionPlainSelects)) {
            return;
        }
        //解析权限表达式
        MultiOrExpression permissionExpression = parseDataPermissionExpression(aliasMap, normalDataPermission, specialDataPermission);
        if (permissionExpression == null) {
            return;
        }
        //定义计数器
        AtomicInteger count = new AtomicInteger(0);
        for (PlainSelect plainSelect : allPlainSelects) {
            //替换权限数据
            replaceDataPermissionSql(plainSelect.getWhere(), permissionExpression, count);
        }
        if (count.get() > 0) {
            //存在自定义数据权限,不自动拼装where中的数据权限
            return;
        }
        //无默认权限,union plainSelect中都带上数据权限
        for (PlainSelect plainSelect : unionPlainSelects) {
            plainSelect.setWhere(buildExpression(plainSelect.getWhere(), permissionExpression));
        }
    }

    /**
     * 解析权限表达式
     *
     * @param aliasMap              别名字典项
     * @param normalDataPermission  普通的数据权限
     * @param specialDataPermission 特殊的数据权限
     * @return 权限表达式
     */
    private MultiOrExpression parseDataPermissionExpression(Map aliasMap,
                                                            List> normalDataPermission,
                                                            List specialDataPermission) {
        //获取普通权限
        if (CollectionUtils.isEmpty(normalDataPermission) && CollectionUtils.isEmpty(specialDataPermission)) {
            return null;
        }
        //定义组条件
        List orExpressions = new ArrayList<>();
        if (!CollectionUtils.isEmpty(normalDataPermission)) {
            List sonExpressions;
            //处理普通权限
            for (List dataPermissions: normalDataPermission) {
                sonExpressions = new ArrayList<>();
                for (DataPermissionDto item : dataPermissions) {
                    parseExpression(sonExpressions, item, aliasMap);
                }
                orExpressions.add(new MultiAndExpression(sonExpressions));
            }
        }
        if (!CollectionUtils.isEmpty(specialDataPermission)) {
            //处理特殊权限
            try {
                for (String dataPermission: specialDataPermission) {
                    orExpressions.add(CCJSqlParserUtil.parseCondExpression(dataPermission));
                }
            } catch (Exception e) {
                throw new ServiceException(e.getMessage(), e);
            }
        }
        return new MultiOrExpression(orExpressions);
    }

    /**
     * 解析条件
     *
     * @param expressions 表达式列表
     * @param item        权限信息
     * @param aliasMap    别名字典项
     */
    private void parseExpression(List expressions, DataPermissionDto item, Map aliasMap) {
        if (DataPermissionOperateEnum.EQUAL.equals(item.getOperate())) {
            //相等操作
            expressions.add(new EqualsTo(getColumn(item.getColumn(), aliasMap), getValue(item.getValue())));
        } else if (DataPermissionOperateEnum.NOT_EQUAL.equals(item.getOperate())) {
            //不相等操作
            expressions.add(new NotEqualsTo(getColumn(item.getColumn(), aliasMap), getValue(item.getValue())));
        } else if (DataPermissionOperateEnum.IS_NULL.equals(item.getOperate()) || DataPermissionOperateEnum.NOT_NULL.equals(item.getOperate())) {
            //查询空数据或非空数据
            IsBooleanExpression expression = new IsBooleanExpression();
            expression.setIsTrue(DataPermissionOperateEnum.IS_NULL.equals(item.getOperate()));
            expression.setLeftExpression(getColumn(item.getColumn(), aliasMap));
            expressions.add(expression);
        } else if (DataPermissionOperateEnum.LIKE.equals(item.getOperate()) || DataPermissionOperateEnum.NOT_LIKE.equals(item.getOperate())) {
            //相似和不相似操作
            LikeExpression expression = new LikeExpression();
            expression.setNot(DataPermissionOperateEnum.NOT_LIKE.equals(item.getOperate()));
            expression.setLeftExpression(getColumn(item.getColumn(), aliasMap));
            expression.setRightExpression(getValue(item.getValue()));
            expressions.add(expression);
        } else if (DataPermissionOperateEnum.IN.equals(item.getOperate()) || DataPermissionOperateEnum.NOT_IN.equals(item.getOperate())) {
            //in和not in操作
            ExpressionList values = getValues(item.getValue());
            if (CollectionUtils.isEmpty(values.getExpressions())) {
                return;
            }
            InExpression expression = new InExpression(getColumn(item.getColumn(), aliasMap), values);
            expression.setNot(DataPermissionOperateEnum.NOT_IN.equals(item.getOperate()));
            expressions.add(expression);
        } else if (DataPermissionOperateEnum.BETWEEN.equals(item.getOperate()) || DataPermissionOperateEnum.NOT_BETWEEN.equals(item.getOperate())) {
            //区间和不在区间操作
            List values = getValues(item.getValue()).getExpressions();
            if (CollectionUtils.isEmpty(values) || values.size() < 2) {
                return;
            }
            Between expression = new Between();
            expression.setNot(DataPermissionOperateEnum.NOT_BETWEEN.equals(item.getOperate()));
            expression.setLeftExpression(getColumn(item.getColumn(), aliasMap));
            expression.setBetweenExpressionStart(values.get(0));
            expression.setBetweenExpressionEnd(values.get(1));
            expressions.add(expression);
        }
    }

    /**
     * 获取列
     *
     * @param columnName 列名
     * @param aliasMap   别名字典项
     * @return 列字段
     */
    private Column getColumn(String columnName, Map aliasMap) {
        columnName = columnName.replaceAll("[^a-zA-Z0-9._`]+", "");
        if (columnName.contains(".")) {
            String[] strings = columnName.split("\\.");
            strings[0] = aliasMap.getOrDefault(strings[0], strings[0]);
            columnName = String.join(".", strings);
        }
        return new Column(columnName);
    }

    /**
     * 获取值表达式
     *
     * @param value 值
     * @return 值表达式
     */
    private Expression getValue(Object value) {
        if (value == null) {
            return new NullValue();
        }
        if (value instanceof Date) {
            return new DateValue((java.sql.Date) value);
        }
        String val = String.valueOf(value);
        val = val.replace("\\", "")
                .replace("'", "\\'");
        return new StringValue(val);
    }

    /**
     * 获取值表达式列表
     *
     * @param value 值列表
     * @return 值表达式列表
     */
    private ExpressionList getValues(Object value) {
        ExpressionList result = new ExpressionList();
        if (!(value instanceof List)) {
            return result;
        }
        List list = (List) value;
        if (CollectionUtils.isEmpty(list)) {
            return result;
        }
        result.setExpressions(new ArrayList<>());
        list.forEach(item -> result.getExpressions().add(getValue(item)));
        return result;
    }

    /**
     * 替换数据权限sql
     *
     * @param expression          where条件表达式
     * @param permissionCondition 需要替换的条件
     * @param count               计数器
     */
    private void replaceDataPermissionSql(Expression expression, MultiOrExpression permissionCondition, AtomicInteger count) {
        if (expression == null) {
            return;
        }
        if (!(expression instanceof BinaryExpression)) {
            return;
        }
        BinaryExpression binaryExpression = (BinaryExpression) expression;
        Expression leftExpression = binaryExpression.getLeftExpression();
        if (leftExpression instanceof EqualsTo) {
            if (DataPermissionMybatisPlusInterceptor.DATA_PERMISSION_SQL_PLACEHOLDER.equals(leftExpression.toString())) {
                binaryExpression.setLeftExpression(permissionCondition);
                count.incrementAndGet();
            }
        } else if (leftExpression instanceof BinaryExpression) {
            replaceDataPermissionSql(leftExpression, permissionCondition, count);
        }
        Expression rightExpression = binaryExpression.getRightExpression();
        if (rightExpression instanceof EqualsTo) {
            if (DataPermissionMybatisPlusInterceptor.DATA_PERMISSION_SQL_PLACEHOLDER.equals(rightExpression.toString())) {
                binaryExpression.setRightExpression(permissionCondition);
                count.incrementAndGet();
            }
        } else if (rightExpression instanceof BinaryExpression) {
            replaceDataPermissionSql(rightExpression, permissionCondition, count);
        }
    }

    /**
     * 组装条件
     *
     * @param whereExpression          原where条件
     * @param dataPermissionExpression 数据权限条件
     * @return 新条件
     */
    private Expression buildExpression(Expression whereExpression, Expression dataPermissionExpression) {
        if (whereExpression == null) {
            return dataPermissionExpression;
        }
        //条件定义
        List mainExpressions = new ArrayList() {{
            //原条件信息
            add(whereExpression);
            //加入权限条件
            add(dataPermissionExpression);
        }};
        return new MultiAndExpression(mainExpressions);
    }
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy