This commit is contained in:
Jane
2023-12-22 10:59:10 +08:00
parent 751c43e199
commit d1ede2d4aa
2774 changed files with 291509 additions and 0 deletions

View File

@@ -0,0 +1,27 @@
package cn.datax.common.mybatis.annotation;
import java.lang.annotation.*;
/**
* 数据权限过滤注解
* 参考 https://gitee.com/cancerGit/Crown
*/
@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Inherited
public @interface DataScopeAop {
/**
* 表的别名
*/
String alias() default "sys_user";
/**
* 表的部门字段
*/
String deptScopeName() default "create_dept";
/**
* 表的用户字段
*/
String userScopeName() default "create_by";
}

View File

@@ -0,0 +1,125 @@
package cn.datax.common.mybatis.aspectj;
import java.lang.reflect.Method;
import java.util.List;
import java.util.Set;
import cn.datax.common.base.BaseQueryParams;
import cn.datax.common.core.DataConstant;
import cn.datax.common.core.DataRole;
import cn.datax.common.core.DataUser;
import cn.datax.common.mybatis.annotation.DataScopeAop;
import cn.datax.common.utils.SecurityUtil;
import cn.datax.service.system.api.dto.JwtUserDto;
import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.util.StrUtil;
import lombok.extern.slf4j.Slf4j;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.Signature;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
import org.aspectj.lang.annotation.Pointcut;
import org.aspectj.lang.reflect.MethodSignature;
/**
* 数据过滤处理(基于注解式,用于自定义sql
*/
@Slf4j
@Aspect
public class DataScopeAspect {
// 配置织入点
@Pointcut("@annotation(cn.datax.common.mybatis.annotation.DataScopeAop)")
public void dataScopePointCut() {
}
@Before("dataScopePointCut()")
public void doBefore(JoinPoint point) {
handleDataScope(point);
}
protected void handleDataScope(final JoinPoint joinPoint) {
// 获得注解
DataScopeAop dataScope = getAnnotationLog(joinPoint);
if (dataScope == null) {
return;
}
JwtUserDto currentUser = SecurityUtil.getDataUser();
if (null != currentUser) {
// 如果是超级管理员,则不过滤数据
// if (!currentUser.getUser().isAdmin) {
// dataScopeFilter(joinPoint, currentUser, dataScope);
// }
}
}
// /**
// * 数据范围过滤
// *
// * @param user
// * @param dataScope
// */
// private void dataScopeFilter(JoinPoint joinPoint, JwtUserDto user, DataScopeAop dataScope) {
// StringBuilder sqlString = new StringBuilder();
// Set<String> roles = user.getRoles();
// if (CollUtil.isNotEmpty(roles)){
// for (String role : roles){
// String roleDataScope = role.getDataScope();
// if (DataConstant.DataScope.ALL.getKey().equals(roleDataScope)) {
// sqlString = new StringBuilder();
// break;
// } else if (DataConstant.DataScope.CUSTOM.getKey().equals(roleDataScope)) {
// sqlString.append(StrUtil.format(
// " OR {}.{} IN ( SELECT dept_id FROM sys_role_dept WHERE role_id = {} ) "
// ,dataScope.alias()
// ,dataScope.deptScopeName()
// ,"'" + role.getId() + "'"
// ));
// } else if (DataConstant.DataScope.DEPT.getKey().equals(roleDataScope)) {
// sqlString.append(StrUtil.format(
// " OR {}.{} = {} "
// ,dataScope.alias()
// ,dataScope.deptScopeName()
// ,"'" + user.getDept() + "'"
// ));
// } else if (DataConstant.DataScope.DEPTANDCHILD.getKey().equals(roleDataScope)) {
// sqlString.append(StrUtil.format(
// " OR {}.{} IN ( SELECT descendant FROM sys_dept_relation WHERE ancestor = {} )"
// ,dataScope.alias()
// ,dataScope.deptScopeName()
// ,"'" + user.getDept() + "'"
// ));
// } else if (DataConstant.DataScope.SELF.getKey().equals(roleDataScope)) {
// if (StrUtil.isNotBlank(dataScope.alias())) {
// sqlString.append(StrUtil.format(" OR {}.{} = {} "
// ,dataScope.alias()
// ,dataScope.userScopeName()
// ,user.getId()));
// } else {
// // 数据权限为仅本人且没有alias别名不查询任何数据
// sqlString.append(" OR 1=0 ");
// }
// }
// }
// }
// if (StrUtil.isNotBlank(sqlString.toString())) {
// BaseQueryParams baseQueryParams = (BaseQueryParams) joinPoint.getArgs()[0];
// baseQueryParams.setDataScope(" AND (" + sqlString.substring(4) + ")");
// }
// log.info("数据范围过滤:{}", sqlString);
// }
/**
* 是否存在注解,如果存在就获取
*/
private DataScopeAop getAnnotationLog(JoinPoint joinPoint) {
Signature signature = joinPoint.getSignature();
MethodSignature methodSignature = (MethodSignature) signature;
Method method = methodSignature.getMethod();
if (method != null) {
return method.getAnnotation(DataScopeAop.class);
}
return null;
}
}

View File

@@ -0,0 +1,58 @@
package cn.datax.common.mybatis.config;
import cn.datax.common.mybatis.aspectj.DataScopeAspect;
import cn.datax.common.mybatis.injector.DataLogicSqlInjector;
import cn.datax.common.mybatis.interceptor.DataScopeInterceptor;
import com.baomidou.mybatisplus.extension.plugins.PaginationInterceptor;
import org.mybatis.spring.annotation.MapperScan;
import org.springframework.context.annotation.Bean;
import org.springframework.transaction.annotation.EnableTransactionManagement;
@MapperScan({"cn.datax.service.**.dao","com.platform.dts.mapper"})
@EnableTransactionManagement
public class DataBatisPlusConfig {
/**
* 分页插件
*
* @return PaginationInterceptor
*/
@Bean
public PaginationInterceptor paginationInterceptor() {
return new PaginationInterceptor();
}
/**
* 数据权限插件
*
* @return DataScopeInterceptor
*/
@Bean
public DataScopeInterceptor dataScopeInterceptor() {
return new DataScopeInterceptor();
}
/**
* 数据过滤处理(基于注解式)
*
* @return dataScopeAspect
*/
@Bean
public DataScopeAspect dataScopeAspect() {
return new DataScopeAspect();
}
/**
* 自定义 SqlInjector
* 里面包含自定义的全局方法
*/
@Bean
public DataLogicSqlInjector myLogicSqlInjector() {
return new DataLogicSqlInjector();
}
@Bean
public DataMetaObjectHandler dataMetaObjectHandler() {
return new DataMetaObjectHandler();
}
}

View File

@@ -0,0 +1,34 @@
package cn.datax.common.mybatis.config;
import cn.datax.common.core.DataConstant;
import cn.datax.common.utils.SecurityUtil;
import com.baomidou.mybatisplus.core.handlers.MetaObjectHandler;
import org.apache.ibatis.reflection.MetaObject;
import java.time.LocalDateTime;
public class DataMetaObjectHandler implements MetaObjectHandler {
@Override
public void insertFill(MetaObject metaObject) {
this.strictInsertFill(metaObject, "createTime", LocalDateTime.class, LocalDateTime.now());
this.strictInsertFill(metaObject, "updateTime", LocalDateTime.class, LocalDateTime.now());
this.strictInsertFill(metaObject, "status", String.class, DataConstant.EnableState.ENABLE.getKey());
this.strictInsertFill(metaObject, "createBy", String.class, SecurityUtil.getUserId());
this.strictInsertFill(metaObject, "updateBy", String.class, SecurityUtil.getUserId());
boolean bolCreateDept = metaObject.hasSetter("createDept");
if (bolCreateDept) {
this.strictInsertFill(metaObject, "createDept", String.class, SecurityUtil.getUserDeptId());
}
boolean bolFlowStatus = metaObject.hasSetter("flowStatus");
if (bolFlowStatus) {
this.strictInsertFill(metaObject, "flowStatus", String.class, DataConstant.AuditState.WAIT.getKey());
}
}
@Override
public void updateFill(MetaObject metaObject) {
this.strictUpdateFill(metaObject, "updateTime", LocalDateTime.class, LocalDateTime.now());
this.strictUpdateFill(metaObject, "updateBy", String.class, SecurityUtil.getUserId());
}
}

View File

@@ -0,0 +1,27 @@
package cn.datax.common.mybatis.injector;
import cn.datax.common.mybatis.injector.methods.SelectListDataScope;
import cn.datax.common.mybatis.injector.methods.SelectPageDataScope;
import com.baomidou.mybatisplus.core.injector.AbstractMethod;
import com.baomidou.mybatisplus.core.injector.DefaultSqlInjector;
import java.util.List;
/**
* 自定义 SqlInjector
*/
public class DataLogicSqlInjector extends DefaultSqlInjector {
/**
* 如果只需增加方法保留MP自带方法
* 可以super.getMethodList() 再add
* @return
*/
@Override
public List<AbstractMethod> getMethodList(Class<?> mapperClass) {
List<AbstractMethod> methodList = super.getMethodList(mapperClass);
methodList.add(new SelectListDataScope());
methodList.add(new SelectPageDataScope());
return methodList;
}
}

View File

@@ -0,0 +1,21 @@
package cn.datax.common.mybatis.injector.methods;
import com.baomidou.mybatisplus.core.enums.SqlMethod;
import com.baomidou.mybatisplus.core.injector.AbstractMethod;
import com.baomidou.mybatisplus.core.metadata.TableInfo;
import org.apache.ibatis.mapping.MappedStatement;
import org.apache.ibatis.mapping.SqlSource;
public class SelectListDataScope extends AbstractMethod {
public SelectListDataScope() {
}
@Override
public MappedStatement injectMappedStatement(Class<?> mapperClass, Class<?> modelClass, TableInfo tableInfo) {
SqlMethod sqlMethod = SqlMethod.SELECT_LIST;
String sql = String.format(sqlMethod.getSql(), this.sqlFirst(), this.sqlSelectColumns(tableInfo, true), tableInfo.getTableName(), this.sqlWhereEntityWrapper(true, tableInfo), this.sqlComment());
SqlSource sqlSource = this.languageDriver.createSqlSource(this.configuration, sql, modelClass);
return this.addSelectMappedStatementForTable(mapperClass, "selectListDataScope", sqlSource, tableInfo);
}
}

View File

@@ -0,0 +1,21 @@
package cn.datax.common.mybatis.injector.methods;
import com.baomidou.mybatisplus.core.enums.SqlMethod;
import com.baomidou.mybatisplus.core.injector.AbstractMethod;
import com.baomidou.mybatisplus.core.metadata.TableInfo;
import org.apache.ibatis.mapping.MappedStatement;
import org.apache.ibatis.mapping.SqlSource;
public class SelectPageDataScope extends AbstractMethod {
public SelectPageDataScope() {
}
@Override
public MappedStatement injectMappedStatement(Class<?> mapperClass, Class<?> modelClass, TableInfo tableInfo) {
SqlMethod sqlMethod = SqlMethod.SELECT_PAGE;
String sql = String.format(sqlMethod.getSql(), this.sqlFirst(), this.sqlSelectColumns(tableInfo, true), tableInfo.getTableName(), this.sqlWhereEntityWrapper(true, tableInfo), this.sqlComment());
SqlSource sqlSource = this.languageDriver.createSqlSource(this.configuration, sql, modelClass);
return this.addSelectMappedStatementForTable(mapperClass, "selectPageDataScope", sqlSource, tableInfo);
}
}

View File

@@ -0,0 +1,162 @@
package cn.datax.common.mybatis.interceptor;
import cn.datax.common.base.DataScope;
import cn.datax.common.core.DataConstant;
import cn.datax.common.core.DataRole;
import cn.datax.common.core.DataUser;
import cn.datax.common.utils.SecurityUtil;
import cn.datax.service.system.api.dto.JwtUserDto;
import cn.datax.service.system.api.dto.UserLoginDto;
import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.util.StrUtil;
import com.baomidou.mybatisplus.core.toolkit.PluginUtils;
import com.baomidou.mybatisplus.extension.handlers.AbstractSqlParserHandler;
import lombok.SneakyThrows;
import lombok.extern.slf4j.Slf4j;
import org.apache.ibatis.executor.statement.StatementHandler;
import org.apache.ibatis.mapping.BoundSql;
import org.apache.ibatis.mapping.MappedStatement;
import org.apache.ibatis.mapping.SqlCommandType;
import org.apache.ibatis.plugin.*;
import org.apache.ibatis.reflection.MetaObject;
import org.apache.ibatis.reflection.SystemMetaObject;
import java.sql.Connection;
import java.util.List;
import java.util.Map;
import java.util.Properties;
import java.util.Set;
/**
* mybatis 数据权限拦截器
*/
@Slf4j
@Intercepts({@Signature(type = StatementHandler.class, method = "prepare", args = {Connection.class, Integer.class})})
public class DataScopeInterceptor extends AbstractSqlParserHandler implements Interceptor {
@Override
@SneakyThrows
public Object intercept(Invocation invocation) {
StatementHandler statementHandler = (StatementHandler) PluginUtils.realTarget(invocation.getTarget());
MetaObject metaObject = SystemMetaObject.forObject(statementHandler);
this.sqlParser(metaObject);
// 先判断是不是SELECT操作
MappedStatement mappedStatement = (MappedStatement) metaObject.getValue("delegate.mappedStatement");
if (!SqlCommandType.SELECT.equals(mappedStatement.getSqlCommandType())) {
return invocation.proceed();
}
BoundSql boundSql = (BoundSql) metaObject.getValue("delegate.boundSql");
String originalSql = boundSql.getSql();
Object parameterObject = boundSql.getParameterObject();
//查找参数中包含DataScope类型的参数
DataScope dataScope = findDataScopeObject(parameterObject);
if (dataScope != null) {
// 获取当前的用户
JwtUserDto currentUser = SecurityUtil.getDataUser();
if (null != currentUser) {
UserLoginDto user = currentUser.getUser();
// 如果是超级管理员,则不过滤数据
// if (!user.isAdmin) {
// String sqlString = dataScopeFilter(currentUser, dataScope);
// if (StrUtil.isNotBlank(sqlString)) {
// originalSql = "SELECT * FROM (" + originalSql + ") TEMP_DATA_SCOPE WHERE 1=1 AND (" + sqlString.substring(4) + ")";
// metaObject.setValue("delegate.boundSql.sql", originalSql);
// }
// }
}
}
return invocation.proceed();
}
// /**
// * 数据范围过滤
// *
// * @param user
// * @param dataScope
// */
// private String dataScopeFilter(JwtUserDto user, DataScope dataScope) {
// StringBuilder sqlString = new StringBuilder();
// Set<String> roles = user.getRoles();
// if (CollUtil.isNotEmpty(roles)){
// for (String role : roles){
//// String roleDataScope = role.getDataScope();
// if (DataConstant.DataScope.ALL.getKey().equals(roleDataScope)) {
// sqlString = new StringBuilder();
// break;
// } else if (DataConstant.DataScope.CUSTOM.getKey().equals(roleDataScope)) {
// sqlString.append(StrUtil.format(
// " OR {} IN ( SELECT dept_id FROM sys_role_dept WHERE role_id = {} ) "
// ,dataScope.getDeptScopeName()
// ,"'" + role + "'"
// ));
// } else if (DataConstant.DataScope.DEPT.getKey().equals(roleDataScope)) {
// sqlString.append(StrUtil.format(
// " OR {} = {} "
// ,dataScope.getDeptScopeName()
// ,"'" + user.getUser().getDept() + "'"
// ));
// } else if (DataConstant.DataScope.DEPTANDCHILD.getKey().equals(roleDataScope)) {
// sqlString.append(StrUtil.format(
// " OR {} IN ( SELECT descendant FROM sys_dept_relation WHERE ancestor = {} )"
// ,dataScope.getDeptScopeName()
// ,"'" + user.getUser().getDept() + "'"
// ));
// } else if (DataConstant.DataScope.SELF.getKey().equals(roleDataScope)) {
// sqlString.append(StrUtil.format(" OR {} = {} "
// ,dataScope.getUserScopeName()
// ,"'" + user.getUser().getId() + "'"
// ));
// }
// }
// }
// log.info("数据范围过滤:{}", sqlString);
// return sqlString.toString();
// }
/**
* 生成拦截对象的代理
*
* @param target 目标对象
* @return 代理对象
*/
@Override
public Object plugin(Object target) {
if (target instanceof StatementHandler) {
return Plugin.wrap(target, this);
}
return target;
}
/**
* mybatis配置的属性
*
* @param properties mybatis配置的属性
*/
@Override
public void setProperties(Properties properties) {
}
/**
* 查找参数是否包括DataScope对象
*
* @param parameterObj 参数列表
* @return DataScope
*/
private DataScope findDataScopeObject(Object parameterObj) {
if (parameterObj instanceof DataScope) {
return (DataScope) parameterObj;
} else if (parameterObj instanceof Map) {
for (Object val : ((Map<?, ?>) parameterObj).values()) {
if (val instanceof DataScope) {
return (DataScope) val;
}
}
}
return null;
}
}

View File

@@ -0,0 +1,2 @@
org.springframework.boot.autoconfigure.EnableAutoConfiguration=\
cn.datax.common.mybatis.config.DataBatisPlusConfig