|
@@ -0,0 +1,177 @@
|
|
|
+package com.leromro.framework.interceptor;
|
|
|
+
|
|
|
+import cn.hutool.core.collection.CollUtil;
|
|
|
+import cn.hutool.core.map.MapUtil;
|
|
|
+import cn.hutool.core.util.ObjectUtil;
|
|
|
+import com.baomidou.mybatisplus.core.toolkit.PluginUtils;
|
|
|
+import com.baomidou.mybatisplus.extension.plugins.inner.InnerInterceptor;
|
|
|
+import com.leromro.common.core.domain.ListPermission;
|
|
|
+import com.leromro.common.core.domain.entity.SysUser;
|
|
|
+import com.leromro.common.core.domain.model.LoginUser;
|
|
|
+import com.leromro.common.utils.PermissionUtil;
|
|
|
+import com.leromro.common.utils.SecurityUtils;
|
|
|
+import com.leromro.common.utils.ServletUtils;
|
|
|
+import com.leromro.common.utils.TableUtil;
|
|
|
+import lombok.extern.slf4j.Slf4j;
|
|
|
+import net.sf.jsqlparser.JSQLParserException;
|
|
|
+import net.sf.jsqlparser.expression.Expression;
|
|
|
+import net.sf.jsqlparser.expression.StringValue;
|
|
|
+import net.sf.jsqlparser.expression.operators.conditional.AndExpression;
|
|
|
+import net.sf.jsqlparser.expression.operators.relational.EqualsTo;
|
|
|
+import net.sf.jsqlparser.parser.CCJSqlParserUtil;
|
|
|
+import net.sf.jsqlparser.parser.SimpleNode;
|
|
|
+import net.sf.jsqlparser.schema.Column;
|
|
|
+import net.sf.jsqlparser.schema.Table;
|
|
|
+import net.sf.jsqlparser.statement.select.*;
|
|
|
+import org.apache.commons.lang3.StringUtils;
|
|
|
+import org.apache.commons.lang3.reflect.FieldUtils;
|
|
|
+import org.apache.ibatis.executor.Executor;
|
|
|
+import org.apache.ibatis.executor.statement.StatementHandler;
|
|
|
+import org.apache.ibatis.mapping.BoundSql;
|
|
|
+import org.apache.ibatis.mapping.MappedStatement;
|
|
|
+import org.apache.ibatis.plugin.Intercepts;
|
|
|
+import org.apache.ibatis.plugin.Signature;
|
|
|
+import org.apache.ibatis.session.ResultHandler;
|
|
|
+import org.apache.ibatis.session.RowBounds;
|
|
|
+
|
|
|
+
|
|
|
+import java.lang.reflect.Field;
|
|
|
+import java.sql.Connection;
|
|
|
+import java.util.Collection;
|
|
|
+import java.util.HashMap;
|
|
|
+import java.util.List;
|
|
|
+import java.util.Map;
|
|
|
+import java.util.stream.Collectors;
|
|
|
+import java.util.stream.Stream;
|
|
|
+
|
|
|
+/**
|
|
|
+ * @author yanglongping
|
|
|
+ * Executor (update, query, flushStatements, commit, rollback, getTransaction, close, isClosed) 拦截执行器的方法;
|
|
|
+ * ParameterHandler (getParameterObject, setParameters) 拦截参数的处理;
|
|
|
+ * ResultSetHandler (handleResultSets, handleOutputParameters) 拦截结果集的处理;
|
|
|
+ * StatementHandler (prepare, parameterize, batch, update, query) 拦截Sql语法构建的处理
|
|
|
+ */
|
|
|
+@Slf4j
|
|
|
+@Intercepts({@Signature(type = StatementHandler.class, method = "query", args = {Connection.class, Integer.class})})
|
|
|
+public class ListPermissionInterceptor implements InnerInterceptor {
|
|
|
+
|
|
|
+ private static final Map<String, String> fieldMap = MapUtil.builder(new HashMap<String, String>())
|
|
|
+ .put("province_code","provinceCode")
|
|
|
+ .put("city_code","cityCode")
|
|
|
+ .put("district_code", "districtCode")
|
|
|
+ .build();
|
|
|
+
|
|
|
+ @Override
|
|
|
+ public void beforeQuery(Executor executor, MappedStatement ms, Object parameterObject, RowBounds rowBounds, ResultHandler resultHandler, BoundSql boundSql) {
|
|
|
+ // 1.判断是否需要修改SQL
|
|
|
+ ListPermission permission = PermissionUtil.findPermission(parameterObject).orElse(null); //获取数据权限参数
|
|
|
+ //如果不存在校验类,或者校验类中不存在校验字段,或权限实体为空,则跳过拦截器
|
|
|
+ if (permission == null || StringUtils.isBlank(permission.getPermissionGroup()) || permission.getAClass() == null) return;
|
|
|
+ //获取待校验字段
|
|
|
+ List<String> groupList = Stream.of(StringUtils.split(permission.getPermissionGroup(), ","))
|
|
|
+ .filter(StringUtils::isNotBlank)
|
|
|
+ .map(String::trim)
|
|
|
+ .collect(Collectors.toList());
|
|
|
+ SysUser user = SecurityUtils.getLoginUser().getUser();
|
|
|
+ //获取权限实体所有字段
|
|
|
+ List<Field> fields = FieldUtils.getAllFieldsList(permission.getAClass());
|
|
|
+ //获取表主键名称
|
|
|
+ String tableIdName = TableUtil.getTableIdName(fields);
|
|
|
+ //获取表名
|
|
|
+ String tableName = TableUtil.getTableName(permission.getAClass());
|
|
|
+ //获取权限实体所有校验字段
|
|
|
+ List<String> fieldList = PermissionUtil.getGroupMappers(permission.getAClass());
|
|
|
+ if (CollUtil.isEmpty(fieldList)) return;
|
|
|
+ //获取fieldList中groupList的字段
|
|
|
+ List<String> groupFieldList = groupList.stream()
|
|
|
+ .filter(fieldList::contains)
|
|
|
+ .collect(Collectors.toList());
|
|
|
+ if (CollUtil.isEmpty(groupFieldList)) return;
|
|
|
+ // 2.根据职责、权限实体修改SQL
|
|
|
+ String oldSql = boundSql.getSql();
|
|
|
+// log.info("targetSql:{}", oldSql);
|
|
|
+ String targetSql = "";
|
|
|
+ try {
|
|
|
+ Select selectStatement = (Select) CCJSqlParserUtil.parse(oldSql);
|
|
|
+ SelectBody selectBody = selectStatement.getSelectBody();
|
|
|
+ if (selectBody == null) {
|
|
|
+ return;
|
|
|
+ }
|
|
|
+ if (selectBody instanceof PlainSelect) {
|
|
|
+ PlainSelect plainSelect = (PlainSelect) selectBody;
|
|
|
+ // 获取所有表及其别名
|
|
|
+ Map<String, String> tableAliases = getAllTableAliases(plainSelect);
|
|
|
+ //获取别名
|
|
|
+ String alias = tableAliases.getOrDefault(tableName, null);
|
|
|
+ //拼接where
|
|
|
+ Expression where = plainSelect.getWhere();
|
|
|
+ for (String column : groupFieldList) {
|
|
|
+ // 检查 column 是否与用户字段相同
|
|
|
+ String userFieldValue = getUserFieldValue(user, column);
|
|
|
+ if (StringUtils.isBlank(userFieldValue)) {
|
|
|
+ continue;
|
|
|
+ }
|
|
|
+ if (StringUtils.isNotBlank(alias)){
|
|
|
+ column = alias + "." + column;
|
|
|
+ }
|
|
|
+ EqualsTo usesEqualsTo = new EqualsTo();
|
|
|
+ usesEqualsTo.setLeftExpression(new Column(column));
|
|
|
+ //当column和user字段相同时,setRightExpression为user中字段的值
|
|
|
+ usesEqualsTo.setRightExpression(new StringValue(userFieldValue));
|
|
|
+ if (where == null) {
|
|
|
+ where = usesEqualsTo;
|
|
|
+ } else {
|
|
|
+ where = new AndExpression(where, usesEqualsTo);
|
|
|
+ }
|
|
|
+ }
|
|
|
+ // 将新的where条件sql 设置回去
|
|
|
+ plainSelect.setWhere(where);
|
|
|
+ targetSql = plainSelect.toString();
|
|
|
+// log.info("targetSql:{}", targetSql);
|
|
|
+ }
|
|
|
+ } catch (JSQLParserException e) {
|
|
|
+ e.printStackTrace();
|
|
|
+ }
|
|
|
+
|
|
|
+ // 3.修改完成的sql 再设置回去
|
|
|
+ PluginUtils.MPBoundSql mpBoundSql = PluginUtils.mpBoundSql(boundSql);
|
|
|
+ mpBoundSql.sql(targetSql);
|
|
|
+ }
|
|
|
+
|
|
|
+ private Map<String, String> getAllTableAliases(PlainSelect plainSelect) {
|
|
|
+ Map<String, String> tableAliases = new HashMap<>();
|
|
|
+ Table table = plainSelect.getFromItem(Table.class);
|
|
|
+ if (ObjectUtil.isNotNull(table.getAlias())) {
|
|
|
+ tableAliases.put(table.getName(),table.getAlias().getName());
|
|
|
+ }
|
|
|
+ List<Join> joins = plainSelect.getJoins();
|
|
|
+ if (CollUtil.isNotEmpty(joins)) {
|
|
|
+ for (Join join : joins) {
|
|
|
+ Table rightItem = (Table)join.getRightItem();
|
|
|
+ if (ObjectUtil.isNotNull(rightItem.getAlias())) {
|
|
|
+ tableAliases.put(rightItem.getName(),rightItem.getAlias().getName());
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ return tableAliases;
|
|
|
+ }
|
|
|
+
|
|
|
+ private String getUserFieldValue(SysUser user, String column) {
|
|
|
+ try {
|
|
|
+ Field field = FieldUtils.getDeclaredField(user.getClass(), fieldMap.get(column), true);
|
|
|
+ if (field != null) {
|
|
|
+ field.setAccessible(true);
|
|
|
+ Object value = field.get(user);
|
|
|
+ if (value != null) {
|
|
|
+ return value.toString();
|
|
|
+ }
|
|
|
+ }
|
|
|
+ } catch (Exception e) {
|
|
|
+ log.error("Error getting user field value for column: {}", column, e);
|
|
|
+ }
|
|
|
+ return null;
|
|
|
+ }
|
|
|
+
|
|
|
+
|
|
|
+}
|