升级spring boot 3.4.4

This commit is contained in:
EightMonth
2025-04-16 16:18:32 +08:00
parent 36caab37e2
commit b70e709e53
22 changed files with 2062 additions and 2058 deletions

View File

@ -112,7 +112,15 @@
<!-- mybatis-plus --> <!-- mybatis-plus -->
<dependency> <dependency>
<groupId>com.baomidou</groupId> <groupId>com.baomidou</groupId>
<artifactId>mybatis-plus-boot-starter</artifactId> <artifactId>mybatis-plus-spring-boot3-starter</artifactId>
<version>${mybatis-plus.version}</version>
</dependency>
<dependency>
<groupId>com.baomidou</groupId>
<!--JDK 11+-->
<artifactId>mybatis-plus-jsqlparser</artifactId>
<!--JDK 8+-->
<!--<artifactId>mybatis-plus-jsqlparser-4.9</artifactId>-->
<version>${mybatis-plus.version}</version> <version>${mybatis-plus.version}</version>
</dependency> </dependency>

View File

@ -20,7 +20,6 @@ import org.jeecg.common.system.vo.LoginUser;
import org.jeecg.common.util.IpUtils; import org.jeecg.common.util.IpUtils;
import org.jeecg.common.util.SpringContextUtils; import org.jeecg.common.util.SpringContextUtils;
import org.jeecg.common.util.oConvertUtils; import org.jeecg.common.util.oConvertUtils;
import org.springframework.core.LocalVariableTableParameterNameDiscoverer;
import org.springframework.core.StandardReflectionParameterNameDiscoverer; import org.springframework.core.StandardReflectionParameterNameDiscoverer;
import org.springframework.stereotype.Component; import org.springframework.stereotype.Component;
import org.springframework.validation.BindingResult; import org.springframework.validation.BindingResult;

View File

@ -1,33 +1,33 @@
package org.jeecg.common.util.sqlInjection; //package org.jeecg.common.util.sqlInjection;
//
import net.sf.jsqlparser.parser.CCJSqlParserDefaultVisitor; //import net.sf.jsqlparser.parser.CCJSqlParserDefaultVisitor;
import net.sf.jsqlparser.parser.SimpleNode; //import net.sf.jsqlparser.parser.SimpleNode;
import net.sf.jsqlparser.statement.select.UnionOp; //import net.sf.jsqlparser.statement.select.UnionOp;
import org.jeecg.common.exception.JeecgSqlInjectionException; //import org.jeecg.common.exception.JeecgSqlInjectionException;
//
/** ///**
* 基于抽象语法树(AST)的注入攻击分析实现 // * 基于抽象语法树(AST)的注入攻击分析实现
* // *
* @author guyadong // * @author guyadong
*/ // */
public class InjectionAstNodeVisitor extends CCJSqlParserDefaultVisitor { //public class InjectionAstNodeVisitor extends CCJSqlParserDefaultVisitor {
public InjectionAstNodeVisitor() { // public InjectionAstNodeVisitor() {
} // }
//
/** // /**
* 处理禁止联合查询 // * 处理禁止联合查询
* // *
* @param node // * @param node
* @param data // * @param data
* @return // * @return
*/ // */
@Override // @Override
public Object visit(SimpleNode node, Object data) { // public Object visit(SimpleNode node, Object data) {
Object value = node.jjtGetValue(); // Object value = node.jjtGetValue();
if (value instanceof UnionOp) { // if (value instanceof UnionOp) {
throw new JeecgSqlInjectionException("DISABLE UNION"); // throw new JeecgSqlInjectionException("DISABLE UNION");
} // }
return super.visit(node, data); // return super.visit(node, data);
} // }
} //}
//

View File

@ -1,172 +1,172 @@
package org.jeecg.common.util.sqlInjection; //package org.jeecg.common.util.sqlInjection;
//
//
import net.sf.jsqlparser.expression.BinaryExpression; //import net.sf.jsqlparser.expression.BinaryExpression;
import net.sf.jsqlparser.expression.Expression; //import net.sf.jsqlparser.expression.Expression;
import net.sf.jsqlparser.expression.Function; //import net.sf.jsqlparser.expression.Function;
import net.sf.jsqlparser.expression.operators.conditional.AndExpression; //import net.sf.jsqlparser.expression.operators.conditional.AndExpression;
import net.sf.jsqlparser.expression.operators.conditional.OrExpression; //import net.sf.jsqlparser.expression.operators.conditional.OrExpression;
import net.sf.jsqlparser.expression.operators.relational.ComparisonOperator; //import net.sf.jsqlparser.expression.operators.relational.ComparisonOperator;
import net.sf.jsqlparser.schema.Column; //import net.sf.jsqlparser.schema.Column;
import net.sf.jsqlparser.statement.select.Join; //import net.sf.jsqlparser.statement.select.Join;
import net.sf.jsqlparser.statement.select.OrderByElement; //import net.sf.jsqlparser.statement.select.OrderByElement;
import net.sf.jsqlparser.statement.select.PlainSelect; //import net.sf.jsqlparser.statement.select.PlainSelect;
import net.sf.jsqlparser.statement.select.SelectItem; //import net.sf.jsqlparser.statement.select.SelectItem;
import net.sf.jsqlparser.statement.select.SubSelect; //import net.sf.jsqlparser.statement.select.SubSelect;
import net.sf.jsqlparser.statement.select.WithItem; //import net.sf.jsqlparser.statement.select.WithItem;
import net.sf.jsqlparser.util.TablesNamesFinder; //import net.sf.jsqlparser.util.TablesNamesFinder;
import org.jeecg.common.exception.JeecgSqlInjectionException; //import org.jeecg.common.exception.JeecgSqlInjectionException;
import org.jeecg.common.util.sqlInjection.parse.ConstAnalyzer; //import org.jeecg.common.util.sqlInjection.parse.ConstAnalyzer;
import org.jeecg.common.util.sqlInjection.parse.ParserSupport; //import org.jeecg.common.util.sqlInjection.parse.ParserSupport;
//
/** ///**
* 基于SQL语法对象的SQL注入攻击分析实现 // * 基于SQL语法对象的SQL注入攻击分析实现
* // *
* @author guyadong // * @author guyadong
*/ // */
public class InjectionSyntaxObjectAnalyzer extends TablesNamesFinder { //public class InjectionSyntaxObjectAnalyzer extends TablesNamesFinder {
/** // /**
* 危险函数名 // * 危险函数名
*/ // */
private static final String DANGROUS_FUNCTIONS = "(sleep|benchmark|extractvalue|updatexml|ST_LatFromGeoHash|ST_LongFromGeoHash|GTID_SUBSET|GTID_SUBTRACT|floor|ST_Pointfromgeohash" // private static final String DANGROUS_FUNCTIONS = "(sleep|benchmark|extractvalue|updatexml|ST_LatFromGeoHash|ST_LongFromGeoHash|GTID_SUBSET|GTID_SUBTRACT|floor|ST_Pointfromgeohash"
+ "|geometrycollection|multipoint|polygon|multipolygon|linestring|multilinestring)"; // + "|geometrycollection|multipoint|polygon|multipolygon|linestring|multilinestring)";
//
private static ThreadLocal<Boolean> disableSubselect = new ThreadLocal<Boolean>() { // private static ThreadLocal<Boolean> disableSubselect = new ThreadLocal<Boolean>() {
@Override // @Override
protected Boolean initialValue() { // protected Boolean initialValue() {
return true; // return true;
}
};
private ConstAnalyzer constAnalyzer = new ConstAnalyzer();
public InjectionSyntaxObjectAnalyzer() {
super();
init(true);
}
@Override
public void visitBinaryExpression(BinaryExpression binaryExpression) {
if (binaryExpression instanceof ComparisonOperator) {
if (isConst(binaryExpression.getLeftExpression()) && isConst(binaryExpression.getRightExpression())) {
/** 禁用恒等式 */
throw new JeecgSqlInjectionException("DISABLE IDENTICAL EQUATION " + binaryExpression);
}
}
super.visitBinaryExpression(binaryExpression);
}
@Override
public void visit(AndExpression andExpression) {
super.visit(andExpression);
checkConstExpress(andExpression.getLeftExpression());
checkConstExpress(andExpression.getRightExpression());
}
@Override
public void visit(OrExpression orExpression) {
super.visit(orExpression);
checkConstExpress(orExpression.getLeftExpression());
checkConstExpress(orExpression.getRightExpression());
}
@Override
public void visit(Function function) {
if (function.getName().matches(DANGROUS_FUNCTIONS)) {
/** 禁用危险函数 */
throw new JeecgSqlInjectionException("DANGROUS FUNCTION: " + function.getName());
}
super.visit(function);
}
@Override
public void visit(WithItem withItem) {
try {
/** 允许 WITH 语句中的子查询 */
disableSubselect.set(false);
super.visit(withItem);
} finally {
disableSubselect.set(true);
}
}
@Override
public void visit(SubSelect subSelect) {
try {
/** 允许语句中的子查询 */
disableSubselect.set(false);
super.visit(subSelect);
} finally {
disableSubselect.set(true);
}
// if (disableSubselect.get()) {
// // 禁用子查询
// throw new JeecgSqlInjectionException("DISABLE subselect " + subSelect);
// } // }
} // };
// private ConstAnalyzer constAnalyzer = new ConstAnalyzer();
@Override //
public void visit(Column tableColumn) { // public InjectionSyntaxObjectAnalyzer() {
if (ParserSupport.isBoolean(tableColumn)) { // super();
throw new JeecgSqlInjectionException("DISABLE CONST BOOL " + tableColumn); // init(true);
} //
super.visit(tableColumn); // }
} //
// @Override
@Override // public void visitBinaryExpression(BinaryExpression binaryExpression) {
public void visit(PlainSelect plainSelect) { // if (binaryExpression instanceof ComparisonOperator) {
if (plainSelect.getSelectItems() != null) { // if (isConst(binaryExpression.getLeftExpression()) && isConst(binaryExpression.getRightExpression())) {
for (SelectItem item : plainSelect.getSelectItems()) { // /** 禁用恒等式 */
item.accept(this); // throw new JeecgSqlInjectionException("DISABLE IDENTICAL EQUATION " + binaryExpression);
} // }
} // }
// super.visitBinaryExpression(binaryExpression);
if (plainSelect.getFromItem() != null) { // }
plainSelect.getFromItem().accept(this); //
} // @Override
// public void visit(AndExpression andExpression) {
if (plainSelect.getJoins() != null) { // super.visit(andExpression);
for (Join join : plainSelect.getJoins()) { // checkConstExpress(andExpression.getLeftExpression());
join.getRightItem().accept(this); // checkConstExpress(andExpression.getRightExpression());
for (Expression e : join.getOnExpressions()) { // }
e.accept(this); //
} // @Override
} // public void visit(OrExpression orExpression) {
} // super.visit(orExpression);
if (plainSelect.getWhere() != null) { // checkConstExpress(orExpression.getLeftExpression());
plainSelect.getWhere().accept(this); // checkConstExpress(orExpression.getRightExpression());
checkConstExpress(plainSelect.getWhere()); // }
} //
// @Override
if (plainSelect.getHaving() != null) { // public void visit(Function function) {
plainSelect.getHaving().accept(this); // if (function.getName().matches(DANGROUS_FUNCTIONS)) {
} // /** 禁用危险函数 */
// throw new JeecgSqlInjectionException("DANGROUS FUNCTION: " + function.getName());
if (plainSelect.getOracleHierarchical() != null) { // }
plainSelect.getOracleHierarchical().accept(this); // super.visit(function);
} // }
if (plainSelect.getOrderByElements() != null) { //
for (OrderByElement orderByElement : plainSelect.getOrderByElements()) { // @Override
orderByElement.getExpression().accept(this); // public void visit(WithItem withItem) {
} // try {
} // /** 允许 WITH 语句中的子查询 */
if (plainSelect.getGroupBy() != null) { // disableSubselect.set(false);
for (Expression expression : plainSelect.getGroupBy().getGroupByExpressionList().getExpressions()) { // super.visit(withItem);
expression.accept(this); // } finally {
} // disableSubselect.set(true);
} // }
} // }
//
private boolean isConst(Expression expression) { // @Override
return constAnalyzer.isConstExpression(expression); // public void visit(SubSelect subSelect) {
} // try {
// /** 允许语句中的子查询 */
private void checkConstExpress(Expression expression) { // disableSubselect.set(false);
if (constAnalyzer.isConstExpression(expression)) { // super.visit(subSelect);
/** 禁用常量表达式 */ // } finally {
throw new JeecgSqlInjectionException("DISABLE CONST EXPRESSION " + expression); // disableSubselect.set(true);
} // }
} //// if (disableSubselect.get()) {
} //// // 禁用子查询
//// throw new JeecgSqlInjectionException("DISABLE subselect " + subSelect);
//// }
// }
//
// @Override
// public void visit(Column tableColumn) {
// if (ParserSupport.isBoolean(tableColumn)) {
// throw new JeecgSqlInjectionException("DISABLE CONST BOOL " + tableColumn);
// }
// super.visit(tableColumn);
// }
//
// @Override
// public void visit(PlainSelect plainSelect) {
// if (plainSelect.getSelectItems() != null) {
// for (SelectItem item : plainSelect.getSelectItems()) {
// item.accept(this);
// }
// }
//
// if (plainSelect.getFromItem() != null) {
// plainSelect.getFromItem().accept(this);
// }
//
// if (plainSelect.getJoins() != null) {
// for (Join join : plainSelect.getJoins()) {
// join.getRightItem().accept(this);
// for (Expression e : join.getOnExpressions()) {
// e.accept(this);
// }
// }
// }
// if (plainSelect.getWhere() != null) {
// plainSelect.getWhere().accept(this);
// checkConstExpress(plainSelect.getWhere());
// }
//
// if (plainSelect.getHaving() != null) {
// plainSelect.getHaving().accept(this);
// }
//
// if (plainSelect.getOracleHierarchical() != null) {
// plainSelect.getOracleHierarchical().accept(this);
// }
// if (plainSelect.getOrderByElements() != null) {
// for (OrderByElement orderByElement : plainSelect.getOrderByElements()) {
// orderByElement.getExpression().accept(this);
// }
// }
// if (plainSelect.getGroupBy() != null) {
// for (Expression expression : plainSelect.getGroupBy().getGroupByExpressionList().getExpressions()) {
// expression.accept(this);
// }
// }
// }
//
// private boolean isConst(Expression expression) {
// return constAnalyzer.isConstExpression(expression);
// }
//
// private void checkConstExpress(Expression expression) {
// if (constAnalyzer.isConstExpression(expression)) {
// /** 禁用常量表达式 */
// throw new JeecgSqlInjectionException("DISABLE CONST EXPRESSION " + expression);
// }
// }
//}
//
//

View File

@ -1,65 +1,65 @@
package org.jeecg.common.util.sqlInjection; //package org.jeecg.common.util.sqlInjection;
//
import org.jeecg.common.exception.JeecgSqlInjectionException; //import org.jeecg.common.exception.JeecgSqlInjectionException;
import org.jeecg.common.util.sqlInjection.parse.ParserSupport; //import org.jeecg.common.util.sqlInjection.parse.ParserSupport;
; //;
//
/** ///**
* SQL注入攻击分析器 // * SQL注入攻击分析器
* // *
* @author guyadong // * @author guyadong
* 参考: // * 参考:
* https://blog.csdn.net/10km/article/details/127767358 // * https://blog.csdn.net/10km/article/details/127767358
* https://gitee.com/l0km/sql2java/tree/dev/sql2java-manager/src/main/java/gu/sql2java/parser // * https://gitee.com/l0km/sql2java/tree/dev/sql2java-manager/src/main/java/gu/sql2java/parser
*/ // */
public class SqlInjectionAnalyzer { //public class SqlInjectionAnalyzer {
//
//启用/关闭注入攻击检查 // //启用/关闭注入攻击检查
private boolean injectCheckEnable = true; // private boolean injectCheckEnable = true;
//防止SQL注入攻击分析实现 // //防止SQL注入攻击分析实现
private final InjectionSyntaxObjectAnalyzer injectionChecker; // private final InjectionSyntaxObjectAnalyzer injectionChecker;
private final InjectionAstNodeVisitor injectionVisitor; // private final InjectionAstNodeVisitor injectionVisitor;
//
public SqlInjectionAnalyzer() { // public SqlInjectionAnalyzer() {
this.injectionChecker = new InjectionSyntaxObjectAnalyzer(); // this.injectionChecker = new InjectionSyntaxObjectAnalyzer();
this.injectionVisitor = new InjectionAstNodeVisitor(); // this.injectionVisitor = new InjectionAstNodeVisitor();
} // }
//
/** // /**
* 启用/关闭注入攻击检查,默认启动 // * 启用/关闭注入攻击检查,默认启动
* // *
* @param enable // * @param enable
* @return // * @return
*/ // */
public SqlInjectionAnalyzer injectCheckEnable(boolean enable) { // public SqlInjectionAnalyzer injectCheckEnable(boolean enable) {
injectCheckEnable = enable; // injectCheckEnable = enable;
return this; // return this;
} // }
//
/** // /**
* 对解析后的SQL对象执行注入攻击分析有注入攻击的危险则抛出异常{@link JeecgSqlInjectionException} // * 对解析后的SQL对象执行注入攻击分析有注入攻击的危险则抛出异常{@link JeecgSqlInjectionException}
* // *
* @param sqlParserInfo // * @param sqlParserInfo
* @throws JeecgSqlInjectionException // * @throws JeecgSqlInjectionException
*/ // */
public ParserSupport.SqlParserInfo injectAnalyse(ParserSupport.SqlParserInfo sqlParserInfo) throws JeecgSqlInjectionException { // public ParserSupport.SqlParserInfo injectAnalyse(ParserSupport.SqlParserInfo sqlParserInfo) throws JeecgSqlInjectionException {
if (null != sqlParserInfo && injectCheckEnable) { // if (null != sqlParserInfo && injectCheckEnable) {
/** SQL注入攻击检查 */ // /** SQL注入攻击检查 */
sqlParserInfo.statement.accept(injectionChecker); // sqlParserInfo.statement.accept(injectionChecker);
sqlParserInfo.simpleNode.jjtAccept(injectionVisitor, null); // sqlParserInfo.simpleNode.jjtAccept(injectionVisitor, null);
} // }
return sqlParserInfo; // return sqlParserInfo;
} // }
//
/** // /**
* sql校验 // * sql校验
*/ // */
public static void checkSql(String sql,boolean check){ // public static void checkSql(String sql,boolean check){
SqlInjectionAnalyzer sqlInjectionAnalyzer = new SqlInjectionAnalyzer(); // SqlInjectionAnalyzer sqlInjectionAnalyzer = new SqlInjectionAnalyzer();
sqlInjectionAnalyzer.injectCheckEnable(check); // sqlInjectionAnalyzer.injectCheckEnable(check);
ParserSupport.SqlParserInfo sqlParserInfo = ParserSupport.parse0(sql, null,null); // ParserSupport.SqlParserInfo sqlParserInfo = ParserSupport.parse0(sql, null,null);
sqlInjectionAnalyzer.injectAnalyse(sqlParserInfo); // sqlInjectionAnalyzer.injectAnalyse(sqlParserInfo);
} // }
} //}
//
//

View File

@ -1,177 +1,177 @@
package org.jeecg.common.util.sqlInjection.parse; //package org.jeecg.common.util.sqlInjection.parse;
//
import lombok.extern.slf4j.Slf4j; //import lombok.extern.slf4j.Slf4j;
import net.sf.jsqlparser.JSQLParserException; //import net.sf.jsqlparser.JSQLParserException;
import net.sf.jsqlparser.parser.*; //import net.sf.jsqlparser.parser.*;
import net.sf.jsqlparser.schema.Column; //import net.sf.jsqlparser.schema.Column;
import net.sf.jsqlparser.statement.Statement; //import net.sf.jsqlparser.statement.Statement;
import net.sf.jsqlparser.statement.select.PlainSelect; //import net.sf.jsqlparser.statement.select.PlainSelect;
import net.sf.jsqlparser.statement.select.Select; //import net.sf.jsqlparser.statement.select.Select;
import net.sf.jsqlparser.statement.select.SelectBody; //import net.sf.jsqlparser.statement.select.SelectBody;
//
import static com.google.common.base.Preconditions.checkArgument; //import static com.google.common.base.Preconditions.checkArgument;
import static com.google.common.base.Preconditions.checkNotNull; //import static com.google.common.base.Preconditions.checkNotNull;
//
import java.lang.reflect.InvocationTargetException; //import java.lang.reflect.InvocationTargetException;
import java.util.regex.Matcher; //import java.util.regex.Matcher;
import java.util.regex.Pattern; //import java.util.regex.Pattern;
//
import com.google.common.base.Throwables; //import com.google.common.base.Throwables;
import org.jeecg.common.exception.JeecgBootException; //import org.jeecg.common.exception.JeecgBootException;
import org.jeecg.common.exception.JeecgSqlInjectionException; //import org.jeecg.common.exception.JeecgSqlInjectionException;
//
/** ///**
* 解析sql支持 // * 解析sql支持
*/ // */
@Slf4j //@Slf4j
public class ParserSupport { //public class ParserSupport {
/** // /**
* 解析SELECT SQL语句,解析失败或非SELECT语句则抛出异常 // * 解析SELECT SQL语句,解析失败或非SELECT语句则抛出异常
* // *
* @param sql // * @param sql
* @return // * @return
*/ // */
public static Select parseSelect(String sql) { // public static Select parseSelect(String sql) {
Statement stmt; // Statement stmt;
try { // try {
stmt = CCJSqlParserUtil.parse(checkNotNull(sql, "sql is null")); // stmt = CCJSqlParserUtil.parse(checkNotNull(sql, "sql is null"));
} catch (JSQLParserException e) { // } catch (JSQLParserException e) {
throw new JeecgBootException(e); // throw new JeecgBootException(e);
} // }
checkArgument(stmt instanceof Select, "%s is not SELECT statment", sql); // checkArgument(stmt instanceof Select, "%s is not SELECT statment", sql);
Select select = (Select) stmt; // Select select = (Select) stmt;
SelectBody selectBody = select.getSelectBody(); // SelectBody selectBody = select.getSelectBody();
// 暂时只支持简单的SELECT xxxx FROM ....语句不支持复杂语句如WITH // // 暂时只支持简单的SELECT xxxx FROM ....语句不支持复杂语句如WITH
checkArgument(selectBody instanceof PlainSelect, "ONLY SUPPORT plain select statement %s", sql); // checkArgument(selectBody instanceof PlainSelect, "ONLY SUPPORT plain select statement %s", sql);
return (Select) stmt; // return (Select) stmt;
} // }
//
/** // /**
* 解析SELECT SQL语句,解析失败或非SELECT语句则 // * 解析SELECT SQL语句,解析失败或非SELECT语句则
* // *
* @param sql // * @param sql
* @return // * @return
*/ // */
public static Select parseSelectUnchecked(String sql) { // public static Select parseSelectUnchecked(String sql) {
try { // try {
return parseSelect(sql); // return parseSelect(sql);
} catch (Exception e) { // } catch (Exception e) {
return null; // return null;
} // }
} // }
//
/** // /**
* 实现SQL语句解析,解析成功则返回解析后的{@link Statement} // * 实现SQL语句解析,解析成功则返回解析后的{@link Statement}
* 并通过{@code visitor}参数提供基于AST(抽象语法树)的遍历所有节点的能力。 // * 并通过{@code visitor}参数提供基于AST(抽象语法树)的遍历所有节点的能力。
* // *
* @param sql SQL语句 // * @param sql SQL语句
* @param visitor 遍历所有节点的{@link SimpleNodeVisitor}接口实例,为{@code null}忽略 // * @param visitor 遍历所有节点的{@link SimpleNodeVisitor}接口实例,为{@code null}忽略
* @param sqlSyntaxNormalizer SQL语句分析转换器为{@code null}忽略 // * @param sqlSyntaxNormalizer SQL语句分析转换器为{@code null}忽略
* @throws JSQLParserException 输入的SQL语句有语法错误 // * @throws JSQLParserException 输入的SQL语句有语法错误
* @see #parse0(String, CCJSqlParserVisitor, SqlSyntaxNormalizer) // * @see #parse0(String, CCJSqlParserVisitor, SqlSyntaxNormalizer)
*/ // */
public static Statement parse(String sql, CCJSqlParserVisitor visitor, SqlSyntaxNormalizer sqlSyntaxNormalizer) throws JSQLParserException { // public static Statement parse(String sql, CCJSqlParserVisitor visitor, SqlSyntaxNormalizer sqlSyntaxNormalizer) throws JSQLParserException {
return parse0(sql, visitor, sqlSyntaxNormalizer).statement; // return parse0(sql, visitor, sqlSyntaxNormalizer).statement;
} // }
//
/** // /**
* 参照{@link CCJSqlParserUtil#parseAST(String)}和{@link CCJSqlParserUtil#parse(String)}实现SQL语句解析, // * 参照{@link CCJSqlParserUtil#parseAST(String)}和{@link CCJSqlParserUtil#parse(String)}实现SQL语句解析,
* 解析成功则返回解析后的{@link SqlParserInfo}对象, // * 解析成功则返回解析后的{@link SqlParserInfo}对象,
* 并通过{@code visitor}参数提供基于AST(抽象语法树)的遍历所有节点的能力。 // * 并通过{@code visitor}参数提供基于AST(抽象语法树)的遍历所有节点的能力。
* // *
* @param sql SQL语句 // * @param sql SQL语句
* @param visitor 遍历所有节点的{@link SimpleNodeVisitor}接口实例,为{@code null}忽略 // * @param visitor 遍历所有节点的{@link SimpleNodeVisitor}接口实例,为{@code null}忽略
* @param sqlSyntaxAnalyzer SQL语句分析转换器为{@code null}忽略 // * @param sqlSyntaxAnalyzer SQL语句分析转换器为{@code null}忽略
* @throws JSQLParserException 输入的SQL语句有语法错误 // * @throws JSQLParserException 输入的SQL语句有语法错误
* @see net.sf.jsqlparser.parser.Node#jjtAccept(SimpleNodeVisitor, Object) // * @see net.sf.jsqlparser.parser.Node#jjtAccept(SimpleNodeVisitor, Object)
*/ // */
public static SqlParserInfo parse0(String sql, CCJSqlParserVisitor visitor, SqlSyntaxNormalizer sqlSyntaxAnalyzer) throws JeecgSqlInjectionException { // public static SqlParserInfo parse0(String sql, CCJSqlParserVisitor visitor, SqlSyntaxNormalizer sqlSyntaxAnalyzer) throws JeecgSqlInjectionException {
//
//检查是否非select开头暂不支持 // //检查是否非select开头暂不支持
if(!sql.toLowerCase().trim().startsWith("select ")) { // if(!sql.toLowerCase().trim().startsWith("select ")) {
log.warn("传入sql 非select开头不支持非select开头的语句解析"); // log.warn("传入sql 非select开头不支持非select开头的语句解析");
return null; // return null;
} // }
//
//检查是否存储过程,暂不支持 // //检查是否存储过程,暂不支持
if(sql.toLowerCase().trim().startsWith("call ")){ // if(sql.toLowerCase().trim().startsWith("call ")){
log.warn("传入call 开头存储过程,不支持存储过程解析!"); // log.warn("传入call 开头存储过程,不支持存储过程解析!");
return null; // return null;
} // }
//
//检查特殊语义的特殊字符,目前检查冒号、$、#三种特殊语义字符 // //检查特殊语义的特殊字符,目前检查冒号、$、#三种特殊语义字符
String specialCharacters = "[:$#]"; // String specialCharacters = "[:$#]";
Pattern pattern = Pattern.compile(specialCharacters); // Pattern pattern = Pattern.compile(specialCharacters);
Matcher matcher = pattern.matcher(sql); // Matcher matcher = pattern.matcher(sql);
if (matcher.find()) { // if (matcher.find()) {
sql = sql.replaceAll("[:$#]", "@"); // sql = sql.replaceAll("[:$#]", "@");
} // }
//
checkArgument(null != sql, "sql is null"); // checkArgument(null != sql, "sql is null");
boolean allowComplexParsing = CCJSqlParserUtil.getNestingDepth(sql) <= CCJSqlParserUtil.ALLOWED_NESTING_DEPTH; // boolean allowComplexParsing = CCJSqlParserUtil.getNestingDepth(sql) <= CCJSqlParserUtil.ALLOWED_NESTING_DEPTH;
//
CCJSqlParser parser = CCJSqlParserUtil.newParser(sql).withAllowComplexParsing(allowComplexParsing); // CCJSqlParser parser = CCJSqlParserUtil.newParser(sql).withAllowComplexParsing(allowComplexParsing);
Statement stmt; // Statement stmt;
try { // try {
stmt = parser.Statement(); // stmt = parser.Statement();
} catch (Exception ex) { // } catch (Exception ex) {
log.error("请注意SQL语法可能存在问题---> {}", ex.getMessage()); // log.error("请注意SQL语法可能存在问题---> {}", ex.getMessage());
throw new JeecgSqlInjectionException("请注意SQL语法可能存在问题:"+sql); // throw new JeecgSqlInjectionException("请注意SQL语法可能存在问题:"+sql);
} // }
if (null != visitor) { // if (null != visitor) {
parser.getASTRoot().jjtAccept(visitor, null); // parser.getASTRoot().jjtAccept(visitor, null);
} // }
if (null != sqlSyntaxAnalyzer) { // if (null != sqlSyntaxAnalyzer) {
stmt.accept(sqlSyntaxAnalyzer.resetChanged()); // stmt.accept(sqlSyntaxAnalyzer.resetChanged());
} // }
return new SqlParserInfo(stmt.toString(), stmt, (SimpleNode) parser.getASTRoot()); // return new SqlParserInfo(stmt.toString(), stmt, (SimpleNode) parser.getASTRoot());
} // }
//
/** // /**
* 调用{@link CCJSqlParser}解析SQL语句部件返回解析生成的对象,如{@code 'ORDER BY id DESC'} // * 调用{@link CCJSqlParser}解析SQL语句部件返回解析生成的对象,如{@code 'ORDER BY id DESC'}
* // *
* @param <T> // * @param <T>
* @param input // * @param input
* @param method 指定调用的{@link CCJSqlParser}解析方法 // * @param method 指定调用的{@link CCJSqlParser}解析方法
* @param targetType 返回的解析对象类型 // * @param targetType 返回的解析对象类型
* @return // * @return
* @since 3.18.3 // * @since 3.18.3
*/ // */
public static <T> T parseComponent(String input, String method, Class<T> targetType) { // public static <T> T parseComponent(String input, String method, Class<T> targetType) {
try { // try {
CCJSqlParser parser = new CCJSqlParser(new StringProvider(input)); // CCJSqlParser parser = new CCJSqlParser(new StringProvider(input));
try { // try {
return checkNotNull(targetType, "targetType is null").cast(parser.getClass().getMethod(method).invoke(parser)); // return checkNotNull(targetType, "targetType is null").cast(parser.getClass().getMethod(method).invoke(parser));
} catch (InvocationTargetException e) { // } catch (InvocationTargetException e) {
Throwables.throwIfUnchecked(e.getTargetException()); // Throwables.throwIfUnchecked(e.getTargetException());
throw new RuntimeException(e.getTargetException()); // throw new RuntimeException(e.getTargetException());
} // }
} catch (IllegalAccessException | NoSuchMethodException | SecurityException e) { // } catch (IllegalAccessException | NoSuchMethodException | SecurityException e) {
Throwables.throwIfUnchecked(e); // Throwables.throwIfUnchecked(e);
throw new RuntimeException(e); // throw new RuntimeException(e);
} // }
} // }
//
/** // /**
* 如果{@link Column}没有定义table,且字段名为true/false(不区分大小写)则视为布尔常量 // * 如果{@link Column}没有定义table,且字段名为true/false(不区分大小写)则视为布尔常量
* // *
* @param column // * @param column
*/ // */
public static boolean isBoolean(Column column) { // public static boolean isBoolean(Column column) {
return null != column && null == column.getTable() && // return null != column && null == column.getTable() &&
Pattern.compile("(true|false)", Pattern.CASE_INSENSITIVE).matcher(column.getColumnName()).matches(); // Pattern.compile("(true|false)", Pattern.CASE_INSENSITIVE).matcher(column.getColumnName()).matches();
} // }
//
public static class SqlParserInfo { // public static class SqlParserInfo {
public String nativeSql; // public String nativeSql;
public Statement statement; // public Statement statement;
public SimpleNode simpleNode; // public SimpleNode simpleNode;
//
SqlParserInfo(String nativeSql, Statement statement, SimpleNode simpleNode) { // SqlParserInfo(String nativeSql, Statement statement, SimpleNode simpleNode) {
this.nativeSql = nativeSql; // this.nativeSql = nativeSql;
this.statement = statement; // this.statement = statement;
this.simpleNode = simpleNode; // this.simpleNode = simpleNode;
} // }
} // }
} //}
//

View File

@ -1,37 +1,37 @@
package org.jeecg.common.util.sqlInjection.parse; //package org.jeecg.common.util.sqlInjection.parse;
//
import net.sf.jsqlparser.util.TablesNamesFinder; //import net.sf.jsqlparser.util.TablesNamesFinder;
//
/** ///**
* SQL语句分析转换器基类<br> // * SQL语句分析转换器基类<br>
* 基于SQL语法对象实现对SQL的修改 // * 基于SQL语法对象实现对SQL的修改
* (暂时用不到) // * (暂时用不到)
* // *
* @author guyadong // * @author guyadong
* @since 3.17.0 // * @since 3.17.0
*/ // */
public class SqlSyntaxNormalizer extends TablesNamesFinder { //public class SqlSyntaxNormalizer extends TablesNamesFinder {
protected static final ThreadLocal<Boolean> changed = new ThreadLocal<>(); // protected static final ThreadLocal<Boolean> changed = new ThreadLocal<>();
//
public SqlSyntaxNormalizer() { // public SqlSyntaxNormalizer() {
super(); // super();
init(true); // init(true);
//
} // }
//
/** // /**
* 语句改变返回{@code true},否则返回{@code false} // * 语句改变返回{@code true},否则返回{@code false}
*/ // */
public boolean changed() { // public boolean changed() {
return Boolean.TRUE.equals(changed.get()); // return Boolean.TRUE.equals(changed.get());
} // }
//
/** // /**
* 复位线程局部变量{@link #changed}状态 // * 复位线程局部变量{@link #changed}状态
*/ // */
public SqlSyntaxNormalizer resetChanged() { // public SqlSyntaxNormalizer resetChanged() {
changed.remove(); // changed.remove();
return this; // return this;
} // }
} //}
//

View File

@ -1,255 +1,255 @@
package org.jeecg.common.util.sqlparse; //package org.jeecg.common.util.sqlparse;
//
import lombok.extern.slf4j.Slf4j; //import lombok.extern.slf4j.Slf4j;
import net.sf.jsqlparser.JSQLParserException; //import net.sf.jsqlparser.JSQLParserException;
import net.sf.jsqlparser.expression.*; //import net.sf.jsqlparser.expression.*;
import net.sf.jsqlparser.parser.CCJSqlParserManager; //import net.sf.jsqlparser.parser.CCJSqlParserManager;
import net.sf.jsqlparser.schema.Column; //import net.sf.jsqlparser.schema.Column;
import net.sf.jsqlparser.schema.Table; //import net.sf.jsqlparser.schema.Table;
import net.sf.jsqlparser.statement.Statement; //import net.sf.jsqlparser.statement.Statement;
import net.sf.jsqlparser.statement.select.*; //import net.sf.jsqlparser.statement.select.*;
import org.jeecg.common.exception.JeecgBootException; //import org.jeecg.common.exception.JeecgBootException;
import org.jeecg.common.util.sqlparse.vo.SelectSqlInfo; //import org.jeecg.common.util.sqlparse.vo.SelectSqlInfo;
//
import java.io.StringReader; //import java.io.StringReader;
import java.util.ArrayList; //import java.util.ArrayList;
import java.util.HashMap; //import java.util.HashMap;
import java.util.List; //import java.util.List;
import java.util.Map; //import java.util.Map;
//
/** ///**
* 解析所有表名和字段的类 // * 解析所有表名和字段的类
*/ // */
@Slf4j //@Slf4j
public class JSqlParserAllTableManager { //public class JSqlParserAllTableManager {
//
private final String sql; // private final String sql;
private final Map<String, SelectSqlInfo> allTableMap = new HashMap<>(); // private final Map<String, SelectSqlInfo> allTableMap = new HashMap<>();
/** // /**
* 别名对应实际表名 // * 别名对应实际表名
*/ // */
private final Map<String, String> tableAliasMap = new HashMap<>(); // private final Map<String, String> tableAliasMap = new HashMap<>();
//
/** // /**
* 解析后的sql // * 解析后的sql
*/ // */
private String parsedSql = null; // private String parsedSql = null;
//
JSqlParserAllTableManager(String selectSql) { // JSqlParserAllTableManager(String selectSql) {
this.sql = selectSql; // this.sql = selectSql;
} // }
//
/** // /**
* 开始解析 // * 开始解析
* // *
* @return // * @return
* @throws JSQLParserException // * @throws JSQLParserException
*/ // */
public Map<String, SelectSqlInfo> parse() throws JSQLParserException { // public Map<String, SelectSqlInfo> parse() throws JSQLParserException {
// 1. 创建解析器 // // 1. 创建解析器
CCJSqlParserManager mgr = new CCJSqlParserManager(); // CCJSqlParserManager mgr = new CCJSqlParserManager();
// 2. 使用解析器解析sql生成具有层次结构的java类 // // 2. 使用解析器解析sql生成具有层次结构的java类
Statement stmt = mgr.parse(new StringReader(this.sql)); // Statement stmt = mgr.parse(new StringReader(this.sql));
if (stmt instanceof Select) { // if (stmt instanceof Select) {
Select selectStatement = (Select) stmt; // Select selectStatement = (Select) stmt;
SelectBody selectBody = selectStatement.getSelectBody(); // SelectBody selectBody = selectStatement.getSelectBody();
this.parsedSql = selectBody.toString(); // this.parsedSql = selectBody.toString();
// 3. 解析select查询sql的信息 // // 3. 解析select查询sql的信息
if (selectBody instanceof PlainSelect) { // if (selectBody instanceof PlainSelect) {
PlainSelect plainSelect = (PlainSelect) selectBody; // PlainSelect plainSelect = (PlainSelect) selectBody;
// 4. 合并 fromItems // // 4. 合并 fromItems
List<FromItem> fromItems = new ArrayList<>(); // List<FromItem> fromItems = new ArrayList<>();
fromItems.add(plainSelect.getFromItem()); // fromItems.add(plainSelect.getFromItem());
// 4.1 处理join的表 // // 4.1 处理join的表
List<Join> joins = plainSelect.getJoins(); // List<Join> joins = plainSelect.getJoins();
if (joins != null) { // if (joins != null) {
joins.forEach(join -> fromItems.add(join.getRightItem())); // joins.forEach(join -> fromItems.add(join.getRightItem()));
} // }
// 5. 处理 fromItems // // 5. 处理 fromItems
for (FromItem fromItem : fromItems) { // for (FromItem fromItem : fromItems) {
// 5.1 通过表名的方式from // // 5.1 通过表名的方式from
if (fromItem instanceof Table) { // if (fromItem instanceof Table) {
this.addSqlInfoByTable((Table) fromItem); // this.addSqlInfoByTable((Table) fromItem);
} // }
// 5.2 通过子查询的方式from // // 5.2 通过子查询的方式from
else if (fromItem instanceof SubSelect) { // else if (fromItem instanceof SubSelect) {
this.handleSubSelect((SubSelect) fromItem); // this.handleSubSelect((SubSelect) fromItem);
} // }
} // }
// 6. 解析 selectFields // // 6. 解析 selectFields
List<SelectItem> selectItems = plainSelect.getSelectItems(); // List<SelectItem> selectItems = plainSelect.getSelectItems();
for (SelectItem selectItem : selectItems) { // for (SelectItem selectItem : selectItems) {
// 6.1 查询的是全部字段 // // 6.1 查询的是全部字段
if (selectItem instanceof AllColumns) { // if (selectItem instanceof AllColumns) {
// 当 selectItem 为 AllColumns 时fromItem 必定为 Table // // 当 selectItem 为 AllColumns 时fromItem 必定为 Table
String tableName = plainSelect.getFromItem(Table.class).getName(); // String tableName = plainSelect.getFromItem(Table.class).getName();
// 此处必定不为空,因为在解析 fromItem 时,已经将表名添加到 allTableMap 中 // // 此处必定不为空,因为在解析 fromItem 时,已经将表名添加到 allTableMap 中
SelectSqlInfo sqlInfo = this.allTableMap.get(tableName); // SelectSqlInfo sqlInfo = this.allTableMap.get(tableName);
assert sqlInfo != null; // assert sqlInfo != null;
// 设置为查询全部字段 // // 设置为查询全部字段
sqlInfo.setSelectAll(true); // sqlInfo.setSelectAll(true);
sqlInfo.setSelectFields(null); // sqlInfo.setSelectFields(null);
sqlInfo.setRealSelectFields(null); // sqlInfo.setRealSelectFields(null);
} // }
// 6.2 查询的是带表别名( u.* )的全部字段 // // 6.2 查询的是带表别名( u.* )的全部字段
else if (selectItem instanceof AllTableColumns) { // else if (selectItem instanceof AllTableColumns) {
AllTableColumns allTableColumns = (AllTableColumns) selectItem; // AllTableColumns allTableColumns = (AllTableColumns) selectItem;
String aliasName = allTableColumns.getTable().getName(); // String aliasName = allTableColumns.getTable().getName();
// 通过别名获取表名 // // 通过别名获取表名
String tableName = this.tableAliasMap.get(aliasName); // String tableName = this.tableAliasMap.get(aliasName);
if (tableName == null) { // if (tableName == null) {
tableName = aliasName; // tableName = aliasName;
} // }
SelectSqlInfo sqlInfo = this.allTableMap.get(tableName); // SelectSqlInfo sqlInfo = this.allTableMap.get(tableName);
// 如果此处为空,则说明该字段是通过子查询获取的,所以可以不处理,只有实际表才需要处理 // // 如果此处为空,则说明该字段是通过子查询获取的,所以可以不处理,只有实际表才需要处理
if (sqlInfo != null) { // if (sqlInfo != null) {
// 设置为查询全部字段 // // 设置为查询全部字段
sqlInfo.setSelectAll(true); // sqlInfo.setSelectAll(true);
sqlInfo.setSelectFields(null); // sqlInfo.setSelectFields(null);
sqlInfo.setRealSelectFields(null); // sqlInfo.setRealSelectFields(null);
} // }
} // }
// 6.3 各种字段表达式处理 // // 6.3 各种字段表达式处理
else if (selectItem instanceof SelectExpressionItem) { // else if (selectItem instanceof SelectExpressionItem) {
SelectExpressionItem selectExpressionItem = (SelectExpressionItem) selectItem; // SelectExpressionItem selectExpressionItem = (SelectExpressionItem) selectItem;
Expression expression = selectExpressionItem.getExpression(); // Expression expression = selectExpressionItem.getExpression();
Alias alias = selectExpressionItem.getAlias(); // Alias alias = selectExpressionItem.getAlias();
this.handleExpression(expression, alias, plainSelect.getFromItem()); // this.handleExpression(expression, alias, plainSelect.getFromItem());
} // }
} // }
} else { // } else {
log.warn("暂时尚未处理该类型的 SelectBody: {}", selectBody.getClass().getName()); // log.warn("暂时尚未处理该类型的 SelectBody: {}", selectBody.getClass().getName());
throw new JeecgBootException("暂时尚未处理该类型的 SelectBody"); // throw new JeecgBootException("暂时尚未处理该类型的 SelectBody");
} // }
} else { // } else {
// 非 select 查询sql不做处理 // // 非 select 查询sql不做处理
throw new JeecgBootException("非 select 查询sql不做处理"); // throw new JeecgBootException("非 select 查询sql不做处理");
} // }
return this.allTableMap; // return this.allTableMap;
} // }
//
/** // /**
* 处理子查询 // * 处理子查询
* // *
* @param subSelect // * @param subSelect
*/ // */
private void handleSubSelect(SubSelect subSelect) { // private void handleSubSelect(SubSelect subSelect) {
try { // try {
String subSelectSql = subSelect.getSelectBody().toString(); // String subSelectSql = subSelect.getSelectBody().toString();
// 递归调用解析 // // 递归调用解析
Map<String, SelectSqlInfo> map = JSqlParserUtils.parseAllSelectTable(subSelectSql); // Map<String, SelectSqlInfo> map = JSqlParserUtils.parseAllSelectTable(subSelectSql);
if (map != null) { // if (map != null) {
this.assignMap(map); // this.assignMap(map);
} // }
} catch (Exception e) { // } catch (Exception e) {
log.error("解析子查询出错", e); // log.error("解析子查询出错", e);
} // }
} // }
//
/** // /**
* 处理查询字段表达式 // * 处理查询字段表达式
* // *
* @param expression // * @param expression
*/ // */
private void handleExpression(Expression expression, Alias alias, FromItem fromItem) { // private void handleExpression(Expression expression, Alias alias, FromItem fromItem) {
// 处理函数式字段 CONCAT(name,'(',age,')') // // 处理函数式字段 CONCAT(name,'(',age,')')
if (expression instanceof Function) { // if (expression instanceof Function) {
Function functionExp = (Function) expression; // Function functionExp = (Function) expression;
List<Expression> expressions = functionExp.getParameters().getExpressions(); // List<Expression> expressions = functionExp.getParameters().getExpressions();
for (Expression expItem : expressions) { // for (Expression expItem : expressions) {
this.handleExpression(expItem, null, fromItem); // this.handleExpression(expItem, null, fromItem);
} // }
return; // return;
} // }
// 处理字段上的子查询 // // 处理字段上的子查询
if (expression instanceof SubSelect) { // if (expression instanceof SubSelect) {
this.handleSubSelect((SubSelect) expression); // this.handleSubSelect((SubSelect) expression);
return; // return;
} // }
// 不处理字面量 // // 不处理字面量
if (expression instanceof StringValue || // if (expression instanceof StringValue ||
expression instanceof NullValue || // expression instanceof NullValue ||
expression instanceof LongValue || // expression instanceof LongValue ||
expression instanceof DoubleValue || // expression instanceof DoubleValue ||
expression instanceof HexValue || // expression instanceof HexValue ||
expression instanceof DateValue || // expression instanceof DateValue ||
expression instanceof TimestampValue || // expression instanceof TimestampValue ||
expression instanceof TimeValue // expression instanceof TimeValue
) { // ) {
return; // return;
} // }
//
// 处理字段 // // 处理字段
if (expression instanceof Column) { // if (expression instanceof Column) {
Column column = (Column) expression; // Column column = (Column) expression;
// 查询字段名 // // 查询字段名
String fieldName = column.getColumnName(); // String fieldName = column.getColumnName();
String aliasName = fieldName; // String aliasName = fieldName;
if (alias != null) { // if (alias != null) {
aliasName = alias.getName(); // aliasName = alias.getName();
} // }
String tableName; // String tableName;
if (column.getTable() != null) { // if (column.getTable() != null) {
// 通过列的表名获取 sqlInfo // // 通过列的表名获取 sqlInfo
// 例如 user.name这里的 tableName 就是 user // // 例如 user.name这里的 tableName 就是 user
tableName = column.getTable().getName(); // tableName = column.getTable().getName();
// 有可能是别名,需要转换为真实表名 // // 有可能是别名,需要转换为真实表名
if (this.tableAliasMap.get(tableName) != null) { // if (this.tableAliasMap.get(tableName) != null) {
tableName = this.tableAliasMap.get(tableName); // tableName = this.tableAliasMap.get(tableName);
} // }
} else { // } else {
// 当column的table为空时说明是 fromItem 中的字段 // // 当column的table为空时说明是 fromItem 中的字段
tableName = ((Table) fromItem).getName(); // tableName = ((Table) fromItem).getName();
} // }
SelectSqlInfo $sqlInfo = this.allTableMap.get(tableName); // SelectSqlInfo $sqlInfo = this.allTableMap.get(tableName);
if ($sqlInfo != null) { // if ($sqlInfo != null) {
$sqlInfo.addSelectField(aliasName, fieldName); // $sqlInfo.addSelectField(aliasName, fieldName);
} else { // } else {
log.warn("发生意外情况,未找到表名为 {} 的 SelectSqlInfo", tableName); // log.warn("发生意外情况,未找到表名为 {} 的 SelectSqlInfo", tableName);
} // }
} // }
} // }
//
/** // /**
* 根据表名添加sqlInfo // * 根据表名添加sqlInfo
* // *
* @param table // * @param table
*/ // */
private void addSqlInfoByTable(Table table) { // private void addSqlInfoByTable(Table table) {
String tableName = table.getName(); // String tableName = table.getName();
// 解析 aliasName // // 解析 aliasName
if (table.getAlias() != null) { // if (table.getAlias() != null) {
this.tableAliasMap.put(table.getAlias().getName(), tableName); // this.tableAliasMap.put(table.getAlias().getName(), tableName);
} // }
SelectSqlInfo sqlInfo = new SelectSqlInfo(this.parsedSql); // SelectSqlInfo sqlInfo = new SelectSqlInfo(this.parsedSql);
sqlInfo.setFromTableName(table.getName()); // sqlInfo.setFromTableName(table.getName());
this.allTableMap.put(sqlInfo.getFromTableName(), sqlInfo); // this.allTableMap.put(sqlInfo.getFromTableName(), sqlInfo);
} // }
//
/** // /**
* 合并map // * 合并map
* // *
* @param source // * @param source
*/ // */
private void assignMap(Map<String, SelectSqlInfo> source) { // private void assignMap(Map<String, SelectSqlInfo> source) {
for (Map.Entry<String, SelectSqlInfo> entry : source.entrySet()) { // for (Map.Entry<String, SelectSqlInfo> entry : source.entrySet()) {
SelectSqlInfo sqlInfo = this.allTableMap.get(entry.getKey()); // SelectSqlInfo sqlInfo = this.allTableMap.get(entry.getKey());
if (sqlInfo == null) { // if (sqlInfo == null) {
this.allTableMap.put(entry.getKey(), entry.getValue()); // this.allTableMap.put(entry.getKey(), entry.getValue());
} else { // } else {
// 合并 // // 合并
if (sqlInfo.getSelectFields() == null) { // if (sqlInfo.getSelectFields() == null) {
sqlInfo.setSelectFields(entry.getValue().getSelectFields()); // sqlInfo.setSelectFields(entry.getValue().getSelectFields());
} else { // } else {
sqlInfo.getSelectFields().addAll(entry.getValue().getSelectFields()); // sqlInfo.getSelectFields().addAll(entry.getValue().getSelectFields());
} // }
if (sqlInfo.getRealSelectFields() == null) { // if (sqlInfo.getRealSelectFields() == null) {
sqlInfo.setRealSelectFields(entry.getValue().getRealSelectFields()); // sqlInfo.setRealSelectFields(entry.getValue().getRealSelectFields());
} else { // } else {
sqlInfo.getRealSelectFields().addAll(entry.getValue().getRealSelectFields()); // sqlInfo.getRealSelectFields().addAll(entry.getValue().getRealSelectFields());
} // }
} // }
} // }
} // }
//
} //}

View File

@ -1,190 +1,190 @@
package org.jeecg.common.util.sqlparse; //package org.jeecg.common.util.sqlparse;
//
import lombok.extern.slf4j.Slf4j; //import lombok.extern.slf4j.Slf4j;
import net.sf.jsqlparser.JSQLParserException; //import net.sf.jsqlparser.JSQLParserException;
import net.sf.jsqlparser.expression.*; //import net.sf.jsqlparser.expression.*;
import net.sf.jsqlparser.parser.CCJSqlParserManager; //import net.sf.jsqlparser.parser.CCJSqlParserManager;
import net.sf.jsqlparser.schema.Column; //import net.sf.jsqlparser.schema.Column;
import net.sf.jsqlparser.schema.Table; //import net.sf.jsqlparser.schema.Table;
import net.sf.jsqlparser.statement.Statement; //import net.sf.jsqlparser.statement.Statement;
import net.sf.jsqlparser.statement.select.*; //import net.sf.jsqlparser.statement.select.*;
import org.jeecg.common.exception.JeecgBootException; //import org.jeecg.common.exception.JeecgBootException;
import org.jeecg.common.util.oConvertUtils; //import org.jeecg.common.util.oConvertUtils;
import org.jeecg.common.util.sqlparse.vo.SelectSqlInfo; //import org.jeecg.common.util.sqlparse.vo.SelectSqlInfo;
//
import java.io.StringReader; //import java.io.StringReader;
import java.util.List; //import java.util.List;
import java.util.Map; //import java.util.Map;
//
@Slf4j //@Slf4j
public class JSqlParserUtils { //public class JSqlParserUtils {
//
/** // /**
* 解析 查询selectsql的信息 // * 解析 查询selectsql的信息
* 此方法会展开所有子查询到一个map里 // * 此方法会展开所有子查询到一个map里
* key只存真实的表名如果查询的没有真实的表名则会被忽略。 // * key只存真实的表名如果查询的没有真实的表名则会被忽略。
* value只存真实的字段名如果查询的没有真实的字段名则会被忽略。 // * value只存真实的字段名如果查询的没有真实的字段名则会被忽略。
* <p> // * <p>
* 例如SELECT a.*,d.age,(SELECT count(1) FROM sys_depart) AS count FROM (SELECT username AS foo, realname FROM sys_user) a, demo d // * 例如SELECT a.*,d.age,(SELECT count(1) FROM sys_depart) AS count FROM (SELECT username AS foo, realname FROM sys_user) a, demo d
* 解析后的结果为:{sys_user=[username, realname], demo=[age], sys_depart=[]} // * 解析后的结果为:{sys_user=[username, realname], demo=[age], sys_depart=[]}
* // *
* @param selectSql // * @param selectSql
* @return // * @return
*/ // */
public static Map<String, SelectSqlInfo> parseAllSelectTable(String selectSql) throws JSQLParserException { // public static Map<String, SelectSqlInfo> parseAllSelectTable(String selectSql) throws JSQLParserException {
if (oConvertUtils.isEmpty(selectSql)) { // if (oConvertUtils.isEmpty(selectSql)) {
return null; // return null;
} // }
// log.info("解析查询Sql{}", selectSql); // // log.info("解析查询Sql{}", selectSql);
JSqlParserAllTableManager allTableManager = new JSqlParserAllTableManager(selectSql); // JSqlParserAllTableManager allTableManager = new JSqlParserAllTableManager(selectSql);
return allTableManager.parse(); // return allTableManager.parse();
} // }
//
/** // /**
* 解析 查询selectsql的信息子查询嵌套 // * 解析 查询selectsql的信息子查询嵌套
* // *
* @param selectSql // * @param selectSql
* @return // * @return
*/ // */
public static SelectSqlInfo parseSelectSqlInfo(String selectSql) throws JSQLParserException { // public static SelectSqlInfo parseSelectSqlInfo(String selectSql) throws JSQLParserException {
if (oConvertUtils.isEmpty(selectSql)) { // if (oConvertUtils.isEmpty(selectSql)) {
return null; // return null;
} // }
// log.info("解析查询Sql{}", selectSql); // // log.info("解析查询Sql{}", selectSql);
// 使用 JSqlParer 解析sql // // 使用 JSqlParer 解析sql
// 1、创建解析器 // // 1、创建解析器
CCJSqlParserManager mgr = new CCJSqlParserManager(); // CCJSqlParserManager mgr = new CCJSqlParserManager();
// 2、使用解析器解析sql生成具有层次结构的java类 // // 2、使用解析器解析sql生成具有层次结构的java类
Statement stmt = mgr.parse(new StringReader(selectSql)); // Statement stmt = mgr.parse(new StringReader(selectSql));
if (stmt instanceof Select) { // if (stmt instanceof Select) {
Select selectStatement = (Select) stmt; // Select selectStatement = (Select) stmt;
// 3、解析select查询sql的信息 // // 3、解析select查询sql的信息
return JSqlParserUtils.parseBySelectBody(selectStatement.getSelectBody()); // return JSqlParserUtils.parseBySelectBody(selectStatement.getSelectBody());
} else { // } else {
// 非 select 查询sql不做处理 // // 非 select 查询sql不做处理
throw new JeecgBootException("非 select 查询sql不做处理"); // throw new JeecgBootException("非 select 查询sql不做处理");
} // }
} // }
//
/** // /**
* 解析 select 查询sql的信息 // * 解析 select 查询sql的信息
* // *
* @param selectBody // * @param selectBody
* @return // * @return
*/ // */
private static SelectSqlInfo parseBySelectBody(SelectBody selectBody) { // private static SelectSqlInfo parseBySelectBody(SelectBody selectBody) {
// 判断是否使用了union等操作 // // 判断是否使用了union等操作
if (selectBody instanceof SetOperationList) { // if (selectBody instanceof SetOperationList) {
// 如果使用了union等操作则只解析第一个查询 // // 如果使用了union等操作则只解析第一个查询
List<SelectBody> selectBodyList = ((SetOperationList) selectBody).getSelects(); // List<SelectBody> selectBodyList = ((SetOperationList) selectBody).getSelects();
return JSqlParserUtils.parseBySelectBody(selectBodyList.get(0)); // return JSqlParserUtils.parseBySelectBody(selectBodyList.get(0));
} // }
// 简单的select查询 // // 简单的select查询
if (selectBody instanceof PlainSelect) { // if (selectBody instanceof PlainSelect) {
SelectSqlInfo sqlInfo = new SelectSqlInfo(selectBody); // SelectSqlInfo sqlInfo = new SelectSqlInfo(selectBody);
PlainSelect plainSelect = (PlainSelect) selectBody; // PlainSelect plainSelect = (PlainSelect) selectBody;
FromItem fromItem = plainSelect.getFromItem(); // FromItem fromItem = plainSelect.getFromItem();
// 解析 aliasName // // 解析 aliasName
if (fromItem.getAlias() != null) { // if (fromItem.getAlias() != null) {
sqlInfo.setFromTableAliasName(fromItem.getAlias().getName()); // sqlInfo.setFromTableAliasName(fromItem.getAlias().getName());
} // }
// 解析 表名 // // 解析 表名
if (fromItem instanceof Table) { // if (fromItem instanceof Table) {
// 通过表名的方式from // // 通过表名的方式from
Table fromTable = (Table) fromItem; // Table fromTable = (Table) fromItem;
sqlInfo.setFromTableName(fromTable.getName()); // sqlInfo.setFromTableName(fromTable.getName());
} else if (fromItem instanceof SubSelect) { // } else if (fromItem instanceof SubSelect) {
// 通过子查询的方式from // // 通过子查询的方式from
SubSelect fromSubSelect = (SubSelect) fromItem; // SubSelect fromSubSelect = (SubSelect) fromItem;
SelectSqlInfo subSqlInfo = JSqlParserUtils.parseBySelectBody(fromSubSelect.getSelectBody()); // SelectSqlInfo subSqlInfo = JSqlParserUtils.parseBySelectBody(fromSubSelect.getSelectBody());
sqlInfo.setFromSubSelect(subSqlInfo); // sqlInfo.setFromSubSelect(subSqlInfo);
} // }
// 解析 selectFields // // 解析 selectFields
List<SelectItem> selectItems = plainSelect.getSelectItems(); // List<SelectItem> selectItems = plainSelect.getSelectItems();
for (SelectItem selectItem : selectItems) { // for (SelectItem selectItem : selectItems) {
if (selectItem instanceof AllColumns || selectItem instanceof AllTableColumns) { // if (selectItem instanceof AllColumns || selectItem instanceof AllTableColumns) {
// 全部字段 // // 全部字段
sqlInfo.setSelectAll(true); // sqlInfo.setSelectAll(true);
sqlInfo.setSelectFields(null); // sqlInfo.setSelectFields(null);
sqlInfo.setRealSelectFields(null); // sqlInfo.setRealSelectFields(null);
break; // break;
} else if (selectItem instanceof SelectExpressionItem) { // } else if (selectItem instanceof SelectExpressionItem) {
// 获取单个查询字段名 // // 获取单个查询字段名
SelectExpressionItem selectExpressionItem = (SelectExpressionItem) selectItem; // SelectExpressionItem selectExpressionItem = (SelectExpressionItem) selectItem;
Expression expression = selectExpressionItem.getExpression(); // Expression expression = selectExpressionItem.getExpression();
Alias alias = selectExpressionItem.getAlias(); // Alias alias = selectExpressionItem.getAlias();
JSqlParserUtils.handleExpression(sqlInfo, expression, alias); // JSqlParserUtils.handleExpression(sqlInfo, expression, alias);
} // }
} // }
return sqlInfo; // return sqlInfo;
} else { // } else {
log.warn("暂时尚未处理该类型的 SelectBody: {}", selectBody.getClass().getName()); // log.warn("暂时尚未处理该类型的 SelectBody: {}", selectBody.getClass().getName());
throw new JeecgBootException("暂时尚未处理该类型的 SelectBody"); // throw new JeecgBootException("暂时尚未处理该类型的 SelectBody");
} // }
} // }
//
/** // /**
* 处理查询字段表达式 // * 处理查询字段表达式
* // *
* @param sqlInfo // * @param sqlInfo
* @param expression // * @param expression
* @param alias 是否有别名无传null // * @param alias 是否有别名无传null
*/ // */
private static void handleExpression(SelectSqlInfo sqlInfo, Expression expression, Alias alias) { // private static void handleExpression(SelectSqlInfo sqlInfo, Expression expression, Alias alias) {
// 处理函数式字段 CONCAT(name,'(',age,')') // // 处理函数式字段 CONCAT(name,'(',age,')')
if (expression instanceof Function) { // if (expression instanceof Function) {
JSqlParserUtils.handleFunctionExpression((Function) expression, sqlInfo); // JSqlParserUtils.handleFunctionExpression((Function) expression, sqlInfo);
return; // return;
} // }
// 处理字段上的子查询 // // 处理字段上的子查询
if (expression instanceof SubSelect) { // if (expression instanceof SubSelect) {
SubSelect subSelect = (SubSelect) expression; // SubSelect subSelect = (SubSelect) expression;
SelectSqlInfo subSqlInfo = JSqlParserUtils.parseBySelectBody(subSelect.getSelectBody()); // SelectSqlInfo subSqlInfo = JSqlParserUtils.parseBySelectBody(subSelect.getSelectBody());
// 注:字段上的子查询,必须只查询一个字段,否则会报错,所以可以放心合并 // // 注:字段上的子查询,必须只查询一个字段,否则会报错,所以可以放心合并
sqlInfo.getSelectFields().addAll(subSqlInfo.getSelectFields()); // sqlInfo.getSelectFields().addAll(subSqlInfo.getSelectFields());
sqlInfo.getRealSelectFields().addAll(subSqlInfo.getAllRealSelectFields()); // sqlInfo.getRealSelectFields().addAll(subSqlInfo.getAllRealSelectFields());
return; // return;
} // }
// 不处理字面量 // // 不处理字面量
if (expression instanceof StringValue || // if (expression instanceof StringValue ||
expression instanceof NullValue || // expression instanceof NullValue ||
expression instanceof LongValue || // expression instanceof LongValue ||
expression instanceof DoubleValue || // expression instanceof DoubleValue ||
expression instanceof HexValue || // expression instanceof HexValue ||
expression instanceof DateValue || // expression instanceof DateValue ||
expression instanceof TimestampValue || // expression instanceof TimestampValue ||
expression instanceof TimeValue // expression instanceof TimeValue
) { // ) {
return; // return;
} // }
//
// 查询字段名 // // 查询字段名
String selectField = expression.toString(); // String selectField = expression.toString();
// 实际查询字段名 // // 实际查询字段名
String realSelectField = selectField; // String realSelectField = selectField;
// 判断是否有别名 // // 判断是否有别名
if (alias != null) { // if (alias != null) {
selectField = alias.getName(); // selectField = alias.getName();
} // }
// 获取真实字段名 // // 获取真实字段名
if (expression instanceof Column) { // if (expression instanceof Column) {
Column column = (Column) expression; // Column column = (Column) expression;
realSelectField = column.getColumnName(); // realSelectField = column.getColumnName();
} // }
sqlInfo.addSelectField(selectField, realSelectField); // sqlInfo.addSelectField(selectField, realSelectField);
} // }
//
/** // /**
* 处理函数式字段 // * 处理函数式字段
* // *
* @param functionExp // * @param functionExp
* @param sqlInfo // * @param sqlInfo
*/ // */
private static void handleFunctionExpression(Function functionExp, SelectSqlInfo sqlInfo) { // private static void handleFunctionExpression(Function functionExp, SelectSqlInfo sqlInfo) {
List<Expression> expressions = functionExp.getParameters().getExpressions(); // List<Expression> expressions = functionExp.getParameters().getExpressions();
for (Expression expression : expressions) { // for (Expression expression : expressions) {
JSqlParserUtils.handleExpression(sqlInfo, expression, null); // JSqlParserUtils.handleExpression(sqlInfo, expression, null);
} // }
} // }
//
} //}

View File

@ -1,101 +1,101 @@
package org.jeecg.common.util.sqlparse.vo; //package org.jeecg.common.util.sqlparse.vo;
//
import lombok.Data; //import lombok.Data;
import net.sf.jsqlparser.statement.select.SelectBody; //import net.sf.jsqlparser.statement.select.SelectBody;
//
import java.util.HashSet; //import java.util.HashSet;
import java.util.Set; //import java.util.Set;
//
/** ///**
* select 查询 sql 的信息 // * select 查询 sql 的信息
*/ // */
@Data //@Data
public class SelectSqlInfo { //public class SelectSqlInfo {
//
/** // /**
* 查询的表名如果是子查询则此处为null // * 查询的表名如果是子查询则此处为null
*/ // */
private String fromTableName; // private String fromTableName;
/** // /**
* 表别名 // * 表别名
*/ // */
private String fromTableAliasName; // private String fromTableAliasName;
/** // /**
* 通过子查询获取的表信息例如select name from (select * from user) u // * 通过子查询获取的表信息例如select name from (select * from user) u
* 如果不是子查询则为null // * 如果不是子查询则为null
*/ // */
private SelectSqlInfo fromSubSelect; // private SelectSqlInfo fromSubSelect;
/** // /**
* 查询的字段集合,如果是 * 则为null如果设了别名则为别名 // * 查询的字段集合,如果是 * 则为null如果设了别名则为别名
*/ // */
private Set<String> selectFields; // private Set<String> selectFields;
/** // /**
* 真实的查询字段集合,如果是 * 则为null如果设了别名则为原始字段名 // * 真实的查询字段集合,如果是 * 则为null如果设了别名则为原始字段名
*/ // */
private Set<String> realSelectFields; // private Set<String> realSelectFields;
/** // /**
* 是否是查询所有字段 // * 是否是查询所有字段
*/ // */
private boolean selectAll; // private boolean selectAll;
//
/** // /**
* 解析之后的 SQL (关键字都是大写) // * 解析之后的 SQL (关键字都是大写)
*/ // */
private final String parsedSql; // private final String parsedSql;
//
public SelectSqlInfo(String parsedSql) { // public SelectSqlInfo(String parsedSql) {
this.parsedSql = parsedSql; // this.parsedSql = parsedSql;
} // }
//
public SelectSqlInfo(SelectBody selectBody) { // public SelectSqlInfo(SelectBody selectBody) {
this.parsedSql = selectBody.toString(); // this.parsedSql = selectBody.toString();
} // }
//
public void addSelectField(String selectField, String realSelectField) { // public void addSelectField(String selectField, String realSelectField) {
if (this.selectFields == null) { // if (this.selectFields == null) {
this.selectFields = new HashSet<>(); // this.selectFields = new HashSet<>();
} // }
if (this.realSelectFields == null) { // if (this.realSelectFields == null) {
this.realSelectFields = new HashSet<>(); // this.realSelectFields = new HashSet<>();
} // }
this.selectFields.add(selectField); // this.selectFields.add(selectField);
this.realSelectFields.add(realSelectField); // this.realSelectFields.add(realSelectField);
} // }
//
/** // /**
* 获取所有字段,包括子查询里的。 // * 获取所有字段,包括子查询里的。
* // *
* @return // * @return
*/ // */
public Set<String> getAllRealSelectFields() { // public Set<String> getAllRealSelectFields() {
Set<String> fields = new HashSet<>(); // Set<String> fields = new HashSet<>();
// 递归获取所有字段,起个直观的方法名为: // // 递归获取所有字段,起个直观的方法名为:
this.recursiveGetAllFields(this, fields); // this.recursiveGetAllFields(this, fields);
return fields; // return fields;
} // }
//
/** // /**
* 递归获取所有字段 // * 递归获取所有字段
*/ // */
private void recursiveGetAllFields(SelectSqlInfo sqlInfo, Set<String> fields) { // private void recursiveGetAllFields(SelectSqlInfo sqlInfo, Set<String> fields) {
if (!sqlInfo.isSelectAll() && sqlInfo.getRealSelectFields() != null) { // if (!sqlInfo.isSelectAll() && sqlInfo.getRealSelectFields() != null) {
fields.addAll(sqlInfo.getRealSelectFields()); // fields.addAll(sqlInfo.getRealSelectFields());
} // }
if (sqlInfo.getFromSubSelect() != null) { // if (sqlInfo.getFromSubSelect() != null) {
recursiveGetAllFields(sqlInfo.getFromSubSelect(), fields); // recursiveGetAllFields(sqlInfo.getFromSubSelect(), fields);
} // }
} // }
//
@Override // @Override
public String toString() { // public String toString() {
return "SelectSqlInfo{" + // return "SelectSqlInfo{" +
"fromTableName='" + fromTableName + '\'' + // "fromTableName='" + fromTableName + '\'' +
", fromSubSelect=" + fromSubSelect + // ", fromSubSelect=" + fromSubSelect +
", aliasName='" + fromTableAliasName + '\'' + // ", aliasName='" + fromTableAliasName + '\'' +
", selectFields=" + selectFields + // ", selectFields=" + selectFields +
", realSelectFields=" + realSelectFields + // ", realSelectFields=" + realSelectFields +
", selectAll=" + selectAll + // ", selectAll=" + selectAll +
"}"; // "}";
} // }
//
} //}

View File

@ -10,7 +10,7 @@ import com.fasterxml.jackson.datatype.jsr310.deser.LocalTimeDeserializer;
import com.fasterxml.jackson.datatype.jsr310.ser.LocalDateSerializer; import com.fasterxml.jackson.datatype.jsr310.ser.LocalDateSerializer;
import com.fasterxml.jackson.datatype.jsr310.ser.LocalDateTimeSerializer; import com.fasterxml.jackson.datatype.jsr310.ser.LocalDateTimeSerializer;
import com.fasterxml.jackson.datatype.jsr310.ser.LocalTimeSerializer; import com.fasterxml.jackson.datatype.jsr310.ser.LocalTimeSerializer;
import io.micrometer.prometheus.PrometheusMeterRegistry; import io.micrometer.prometheusmetrics.PrometheusMeterRegistry;
import jakarta.annotation.Resource; import jakarta.annotation.Resource;
import org.springframework.beans.factory.InitializingBean; import org.springframework.beans.factory.InitializingBean;
import org.springframework.beans.factory.ObjectProvider; import org.springframework.beans.factory.ObjectProvider;

View File

@ -6,6 +6,8 @@ import java.util.List;
import cn.hutool.core.util.ObjectUtil; import cn.hutool.core.util.ObjectUtil;
import com.baomidou.mybatisplus.extension.plugins.inner.DynamicTableNameInnerInterceptor; import com.baomidou.mybatisplus.extension.plugins.inner.DynamicTableNameInnerInterceptor;
import com.baomidou.mybatisplus.extension.plugins.inner.OptimisticLockerInnerInterceptor; import com.baomidou.mybatisplus.extension.plugins.inner.OptimisticLockerInnerInterceptor;
import net.sf.jsqlparser.expression.Expression;
import net.sf.jsqlparser.expression.LongValue;
import org.jeecg.common.config.TenantContext; import org.jeecg.common.config.TenantContext;
import org.jeecg.common.constant.CommonConstant; import org.jeecg.common.constant.CommonConstant;
import org.jeecg.common.constant.TenantConstant; import org.jeecg.common.constant.TenantConstant;
@ -21,8 +23,8 @@ import com.baomidou.mybatisplus.extension.plugins.handler.TenantLineHandler;
import com.baomidou.mybatisplus.extension.plugins.inner.PaginationInnerInterceptor; import com.baomidou.mybatisplus.extension.plugins.inner.PaginationInnerInterceptor;
import com.baomidou.mybatisplus.extension.plugins.inner.TenantLineInnerInterceptor; import com.baomidou.mybatisplus.extension.plugins.inner.TenantLineInnerInterceptor;
import net.sf.jsqlparser.expression.Expression; //import net.sf.jsqlparser.expression.Expression;
import net.sf.jsqlparser.expression.LongValue; //import net.sf.jsqlparser.expression.LongValue;
/** /**
* 单数据源配置jeecg.datasource.open = false时生效 * 单数据源配置jeecg.datasource.open = false时生效

View File

@ -1,5 +1,6 @@
package org.jeecg.config.oss; package org.jeecg.config.oss;
import jakarta.annotation.PostConstruct;
import lombok.extern.slf4j.Slf4j; import lombok.extern.slf4j.Slf4j;
import org.jeecg.common.constant.CommonConstant; import org.jeecg.common.constant.CommonConstant;
import org.jeecg.common.constant.SymbolConstant; import org.jeecg.common.constant.SymbolConstant;
@ -26,7 +27,7 @@ public class MinioConfig {
@Value(value = "${jeecg.minio.bucketName}") @Value(value = "${jeecg.minio.bucketName}")
private String bucketName; private String bucketName;
@Bean @PostConstruct
public void initMinio(){ public void initMinio(){
if(!minioUrl.startsWith(CommonConstant.STR_HTTP)){ if(!minioUrl.startsWith(CommonConstant.STR_HTTP)){
minioUrl = "http://" + minioUrl; minioUrl = "http://" + minioUrl;

View File

@ -1,5 +1,6 @@
package org.jeecg.config.oss; package org.jeecg.config.oss;
import jakarta.annotation.PostConstruct;
import org.jeecg.common.util.oss.OssBootUtil; import org.jeecg.common.util.oss.OssBootUtil;
import org.springframework.beans.factory.annotation.Value; import org.springframework.beans.factory.annotation.Value;
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty; import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
@ -26,7 +27,7 @@ public class OssConfiguration {
private String staticDomain; private String staticDomain;
@Bean @PostConstruct
public void initOssBootConfiguration() { public void initOssBootConfiguration() {
OssBootUtil.setEndPoint(endpoint); OssBootUtil.setEndPoint(endpoint);
OssBootUtil.setAccessKeyId(accessKeyId); OssBootUtil.setAccessKeyId(accessKeyId);

View File

@ -1,109 +1,109 @@
package org.jeecg.test.sqlparse; //package org.jeecg.test.sqlparse;
//
import net.sf.jsqlparser.JSQLParserException; //import net.sf.jsqlparser.JSQLParserException;
import org.jeecg.common.util.oConvertUtils; //import org.jeecg.common.util.oConvertUtils;
import org.jeecg.common.util.sqlparse.JSqlParserUtils; //import org.jeecg.common.util.sqlparse.JSqlParserUtils;
import org.jeecg.common.util.sqlparse.vo.SelectSqlInfo; //import org.jeecg.common.util.sqlparse.vo.SelectSqlInfo;
import org.junit.Test; //import org.junit.Test;
//
import java.util.Map; //import java.util.Map;
//
/** ///**
* 针对 JSqlParserUtils 的单元测试 // * 针对 JSqlParserUtils 的单元测试
*/ // */
public class JSqlParserUtilsTest { //public class JSqlParserUtilsTest {
//
private static final String[] sqlList = new String[]{ // private static final String[] sqlList = new String[]{
"select * from sys_user", // "select * from sys_user",
"select u.* from sys_user u", // "select u.* from sys_user u",
"select u.*, c.name from sys_user u, demo c", // "select u.*, c.name from sys_user u, demo c",
"select u.age, c.name from sys_user u, demo c", // "select u.age, c.name from sys_user u, demo c",
"select sex, age, c.name from sys_user, demo c", // "select sex, age, c.name from sys_user, demo c",
// 别名测试 // // 别名测试
"select username as realname from sys_user", // "select username as realname from sys_user",
"select username as realname, u.realname as aaa, u.id bbb from sys_user u", // "select username as realname, u.realname as aaa, u.id bbb from sys_user u",
// 不存在真实地查询字段 // // 不存在真实地查询字段
"select count(1) from sys_user", // "select count(1) from sys_user",
// 函数式字段 // // 函数式字段
"select max(sex), id from sys_user", // "select max(sex), id from sys_user",
// 复杂嵌套函数式字段 // // 复杂嵌套函数式字段
"select CONCAT(CONCAT(' _ ', sex), ' - ' , birthday) as info, id from sys_user", // "select CONCAT(CONCAT(' _ ', sex), ' - ' , birthday) as info, id from sys_user",
// 更复杂的嵌套函数式字段 // // 更复杂的嵌套函数式字段
"select CONCAT(CONCAT(101,'_',NULL, DATE(create_time),'_',sex),' - ',birthday) as info, id from sys_user", // "select CONCAT(CONCAT(101,'_',NULL, DATE(create_time),'_',sex),' - ',birthday) as info, id from sys_user",
// 子查询SQL // // 子查询SQL
"select u.name1 as name2 from (select username as name1 from sys_user) u", // "select u.name1 as name2 from (select username as name1 from sys_user) u",
// 多层嵌套子查询SQL // // 多层嵌套子查询SQL
"select u2.name2 as name3 from (select u1.name1 as name2 from (select username as name1 from sys_user) u1) u2", // "select u2.name2 as name3 from (select u1.name1 as name2 from (select username as name1 from sys_user) u1) u2",
// 字段子查询SQL // // 字段子查询SQL
"select id, (select username as name1 from sys_user u2 where u1.id = u2.id) as name2 from sys_user u1", // "select id, (select username as name1 from sys_user u2 where u1.id = u2.id) as name2 from sys_user u1",
// 带条件的SQL不解析where条件里的字段但不影响解析查询字段 // // 带条件的SQL不解析where条件里的字段但不影响解析查询字段
"select username as name1 from sys_user where realname LIKE '%张%'", // "select username as name1 from sys_user where realname LIKE '%张%'",
// 多重复杂关联表查询解析包含的表为sys_user, sys_depart, sys_dict_item, demo // // 多重复杂关联表查询解析包含的表为sys_user, sys_depart, sys_dict_item, demo
"" + // "" +
"SELECT " + // "SELECT " +
" u.*, d.age, sd.item_text AS sex, (SELECT count(sd.id) FROM sys_depart sd) AS count " + // " u.*, d.age, sd.item_text AS sex, (SELECT count(sd.id) FROM sys_depart sd) AS count " +
"FROM " + // "FROM " +
" (SELECT sd.username AS foo, sd.realname FROM sys_user sd) u, " + // " (SELECT sd.username AS foo, sd.realname FROM sys_user sd) u, " +
" demo d " + // " demo d " +
"LEFT JOIN sys_dict_item AS sd ON d.sex = sd.item_value " + // "LEFT JOIN sys_dict_item AS sd ON d.sex = sd.item_value " +
"WHERE sd.dict_id = '3d9a351be3436fbefb1307d4cfb49bf2'", // "WHERE sd.dict_id = '3d9a351be3436fbefb1307d4cfb49bf2'",
}; // };
//
@Test // @Test
public void testParseSelectSql() { // public void testParseSelectSql() {
System.out.println("-----------------------------------------"); // System.out.println("-----------------------------------------");
for (String sql : sqlList) { // for (String sql : sqlList) {
System.out.println("待测试的sql" + sql); // System.out.println("待测试的sql" + sql);
try { // try {
// 解析所有的表名key=表名value=解析后的sql信息 // // 解析所有的表名key=表名value=解析后的sql信息
Map<String, SelectSqlInfo> parsedMap = JSqlParserUtils.parseAllSelectTable(sql); // Map<String, SelectSqlInfo> parsedMap = JSqlParserUtils.parseAllSelectTable(sql);
assert parsedMap != null; // assert parsedMap != null;
for (Map.Entry<String, SelectSqlInfo> entry : parsedMap.entrySet()) { // for (Map.Entry<String, SelectSqlInfo> entry : parsedMap.entrySet()) {
System.out.println("表名:" + entry.getKey()); // System.out.println("表名:" + entry.getKey());
this.printSqlInfo(entry.getValue(), 1); // this.printSqlInfo(entry.getValue(), 1);
} // }
} catch (JSQLParserException e) { // } catch (JSQLParserException e) {
System.out.println("SQL解析出现异常" + e.getMessage()); // System.out.println("SQL解析出现异常" + e.getMessage());
} // }
System.out.println("-----------------------------------------"); // System.out.println("-----------------------------------------");
} // }
} // }
//
private void printSqlInfo(SelectSqlInfo sqlInfo, int level) { // private void printSqlInfo(SelectSqlInfo sqlInfo, int level) {
String beforeStr = this.getBeforeStr(level); // String beforeStr = this.getBeforeStr(level);
if (sqlInfo.getFromTableName() == null) { // if (sqlInfo.getFromTableName() == null) {
// 子查询 // // 子查询
System.out.println(beforeStr + "子查询:" + sqlInfo.getFromSubSelect().getParsedSql()); // System.out.println(beforeStr + "子查询:" + sqlInfo.getFromSubSelect().getParsedSql());
this.printSqlInfo(sqlInfo.getFromSubSelect(), level + 1); // this.printSqlInfo(sqlInfo.getFromSubSelect(), level + 1);
} else { // } else {
// 非子查询 // // 非子查询
System.out.println(beforeStr + "查询的表名:" + sqlInfo.getFromTableName()); // System.out.println(beforeStr + "查询的表名:" + sqlInfo.getFromTableName());
} // }
if (oConvertUtils.isNotEmpty(sqlInfo.getFromTableAliasName())) { // if (oConvertUtils.isNotEmpty(sqlInfo.getFromTableAliasName())) {
System.out.println(beforeStr + "查询的表别名:" + sqlInfo.getFromTableAliasName()); // System.out.println(beforeStr + "查询的表别名:" + sqlInfo.getFromTableAliasName());
} // }
if (sqlInfo.isSelectAll()) { // if (sqlInfo.isSelectAll()) {
System.out.println(beforeStr + "查询的字段:*"); // System.out.println(beforeStr + "查询的字段:*");
} else { // } else {
System.out.println(beforeStr + "查询的字段:" + sqlInfo.getSelectFields()); // System.out.println(beforeStr + "查询的字段:" + sqlInfo.getSelectFields());
System.out.println(beforeStr + "真实的字段:" + sqlInfo.getRealSelectFields()); // System.out.println(beforeStr + "真实的字段:" + sqlInfo.getRealSelectFields());
if (sqlInfo.getFromTableName() == null) { // if (sqlInfo.getFromTableName() == null) {
System.out.println(beforeStr + "所有的字段(包括子查询):" + sqlInfo.getAllRealSelectFields()); // System.out.println(beforeStr + "所有的字段(包括子查询):" + sqlInfo.getAllRealSelectFields());
} // }
} // }
} // }
//
// 打印前缀,根据层级来打印 // // 打印前缀,根据层级来打印
private String getBeforeStr(int level) { // private String getBeforeStr(int level) {
if (level == 0) { // if (level == 0) {
return ""; // return "";
} // }
StringBuilder beforeStr = new StringBuilder(); // StringBuilder beforeStr = new StringBuilder();
for (int i = 0; i < level; i++) { // for (int i = 0; i < level; i++) {
beforeStr.append(" "); // beforeStr.append(" ");
} // }
beforeStr.append("- "); // beforeStr.append("- ");
return beforeStr.toString(); // return beforeStr.toString();
} // }
//
} //}

View File

@ -19,10 +19,10 @@
<groupId>org.hibernate</groupId> <groupId>org.hibernate</groupId>
<artifactId>hibernate-core</artifactId> <artifactId>hibernate-core</artifactId>
</dependency> </dependency>
<dependency> <!--<dependency>
<groupId>org.jeecgframework.boot3</groupId> <groupId>org.jeecgframework.boot3</groupId>
<artifactId>hibernate-re</artifactId> <artifactId>hibernate-re</artifactId>
</dependency> </dependency>-->
<!-- 企业微信/钉钉 api --> <!-- 企业微信/钉钉 api -->
<dependency> <dependency>
@ -30,7 +30,7 @@
<artifactId>weixin4j</artifactId> <artifactId>weixin4j</artifactId>
</dependency> </dependency>
<!-- 积木报表 --> <!-- 积木报表 -->
<dependency> <!--<dependency>
<groupId>org.jeecgframework.jimureport</groupId> <groupId>org.jeecgframework.jimureport</groupId>
<artifactId>jimureport-spring-boot3-starter-fastjson2</artifactId> <artifactId>jimureport-spring-boot3-starter-fastjson2</artifactId>
</dependency> </dependency>
@ -38,11 +38,11 @@
<groupId>org.jeecgframework.jimureport</groupId> <groupId>org.jeecgframework.jimureport</groupId>
<artifactId>jimureport-nosql-starter</artifactId> <artifactId>jimureport-nosql-starter</artifactId>
</dependency> </dependency>
<!-- 积木BI --> &lt;!&ndash; 积木BI &ndash;&gt;
<dependency> <dependency>
<groupId>org.jeecgframework.jimureport</groupId> <groupId>org.jeecgframework.jimureport</groupId>
<artifactId>jimubi-spring-boot3-starter</artifactId> <artifactId>jimubi-spring-boot3-starter</artifactId>
</dependency> </dependency>-->
</dependencies> </dependencies>
</project> </project>

View File

@ -4,8 +4,8 @@ import lombok.extern.slf4j.Slf4j;
import org.jeecg.common.constant.SymbolConstant; import org.jeecg.common.constant.SymbolConstant;
import org.jeecg.common.exception.JeecgSqlInjectionException; import org.jeecg.common.exception.JeecgSqlInjectionException;
import org.jeecg.common.util.oConvertUtils; import org.jeecg.common.util.oConvertUtils;
import org.jeecg.common.util.sqlparse.JSqlParserUtils; //import org.jeecg.common.util.sqlparse.JSqlParserUtils;
import org.jeecg.common.util.sqlparse.vo.SelectSqlInfo; //import org.jeecg.common.util.sqlparse.vo.SelectSqlInfo;
import org.jeecg.config.JeecgBaseConfig; import org.jeecg.config.JeecgBaseConfig;
import org.jeecg.config.firewall.SqlInjection.IDictTableWhiteListHandler; import org.jeecg.config.firewall.SqlInjection.IDictTableWhiteListHandler;
import org.jeecg.config.firewall.interceptor.LowCodeModeInterceptor; import org.jeecg.config.firewall.interceptor.LowCodeModeInterceptor;
@ -63,31 +63,31 @@ public class DictTableWhiteListHandlerImpl implements IDictTableWhiteListHandler
@Override @Override
public boolean isPassBySql(String sql) { public boolean isPassBySql(String sql) {
Map<String, SelectSqlInfo> parsedMap = null; // Map<String, SelectSqlInfo> parsedMap = null;
try { // try {
parsedMap = JSqlParserUtils.parseAllSelectTable(sql); // parsedMap = JSqlParserUtils.parseAllSelectTable(sql);
} catch (Exception e) { // } catch (Exception e) {
log.warn("校验sql语句解析报错{}", e.getMessage()); // log.warn("校验sql语句解析报错{}", e.getMessage());
} // }
// 如果sql有问题则肯定执行不了所以直接返回true // // 如果sql有问题则肯定执行不了所以直接返回true
if (parsedMap == null) { // if (parsedMap == null) {
return true; // return true;
} // }
log.info("获取select sql信息 {} ", parsedMap); // log.info("获取select sql信息 {} ", parsedMap);
// 遍历当前sql中的所有表名如果有其中一个表或表的字段不在白名单中则不通过 // // 遍历当前sql中的所有表名如果有其中一个表或表的字段不在白名单中则不通过
for (Map.Entry<String, SelectSqlInfo> entry : parsedMap.entrySet()) { // for (Map.Entry<String, SelectSqlInfo> entry : parsedMap.entrySet()) {
SelectSqlInfo sqlInfo = entry.getValue(); // SelectSqlInfo sqlInfo = entry.getValue();
if (sqlInfo.isSelectAll()) { // if (sqlInfo.isSelectAll()) {
log.warn("查询语句中包含 * 字段,暂时先通过"); // log.warn("查询语句中包含 * 字段,暂时先通过");
continue; // continue;
} // }
Set<String> queryFields = sqlInfo.getAllRealSelectFields(); // Set<String> queryFields = sqlInfo.getAllRealSelectFields();
// 校验表名和字段是否允许查询 // // 校验表名和字段是否允许查询
String tableName = entry.getKey(); // String tableName = entry.getKey();
if (!this.checkWhiteList(tableName, queryFields)) { // if (!this.checkWhiteList(tableName, queryFields)) {
return false; // return false;
} // }
} // }
return true; return true;
} }
@ -120,20 +120,21 @@ public class DictTableWhiteListHandlerImpl implements IDictTableWhiteListHandler
if (oConvertUtils.isEmpty(tableName)) { if (oConvertUtils.isEmpty(tableName)) {
return true; return true;
} }
if (fields == null || fields.length == 0) { // if (fields == null || fields.length == 0) {
fields = new String[]{"*"}; // fields = new String[]{"*"};
} // }
String sql = "select " + String.join(",", fields) + " from " + tableName; // String sql = "select " + String.join(",", fields) + " from " + tableName;
log.info("字典拼接的查询SQL{}", sql); // log.info("字典拼接的查询SQL{}", sql);
try { // try {
// 进行SQL解析 // // 进行SQL解析
JSqlParserUtils.parseSelectSqlInfo(sql); // JSqlParserUtils.parseSelectSqlInfo(sql);
} catch (Exception e) { // } catch (Exception e) {
// 如果SQL解析失败则通过字段名和表名进行校验 // // 如果SQL解析失败则通过字段名和表名进行校验
return checkWhiteList(tableName, new HashSet<>(Arrays.asList(fields))); // return checkWhiteList(tableName, new HashSet<>(Arrays.asList(fields)));
} // }
// 通过SQL解析进行校验可防止SQL注入 // // 通过SQL解析进行校验可防止SQL注入
return this.isPassBySql(sql); // return this.isPassBySql(sql);
return true;
} }
/** /**

View File

@ -1,124 +1,124 @@
package org.jeecg.config.jimureport; //package org.jeecg.config.jimureport;
//
import com.alibaba.fastjson.JSONObject; //import com.alibaba.fastjson.JSONObject;
import lombok.extern.slf4j.Slf4j; //import lombok.extern.slf4j.Slf4j;
import org.jeecg.common.api.dto.LogDTO; //import org.jeecg.common.api.dto.LogDTO;
import org.jeecg.common.system.api.ISysBaseAPI; //import org.jeecg.common.system.api.ISysBaseAPI;
import org.jeecg.common.system.vo.DictModel; //import org.jeecg.common.system.vo.DictModel;
import org.jeecg.common.util.oConvertUtils; //import org.jeecg.common.util.oConvertUtils;
import org.jeecg.modules.base.service.BaseCommonService; //import org.jeecg.modules.base.service.BaseCommonService;
import org.jeecg.modules.drag.service.IOnlDragExternalService; //import org.jeecg.modules.drag.service.IOnlDragExternalService;
import org.jeecg.modules.drag.vo.DragDictModel; //import org.jeecg.modules.drag.vo.DragDictModel;
import org.jeecg.modules.drag.vo.DragLogDTO; //import org.jeecg.modules.drag.vo.DragLogDTO;
import org.springframework.beans.BeanUtils; //import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired; //import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Lazy; //import org.springframework.context.annotation.Lazy;
import org.springframework.stereotype.Service; //import org.springframework.stereotype.Service;
import org.springframework.util.CollectionUtils; //import org.springframework.util.CollectionUtils;
//
import java.util.ArrayList; //import java.util.ArrayList;
import java.util.HashMap; //import java.util.HashMap;
import java.util.List; //import java.util.List;
import java.util.Map; //import java.util.Map;
//
/** ///**
* @Description: 字典处理 // * @Description: 字典处理
* @Author: lsq // * @Author: lsq
* @Date:2023-01-09 // * @Date:2023-01-09
* @Version:V1.0 // * @Version:V1.0
*/ // */
@Slf4j //@Slf4j
@Service("onlDragExternalServiceImpl") //@Service("onlDragExternalServiceImpl")
public class JimuDragExternalServiceImpl implements IOnlDragExternalService { //public class JimuDragExternalServiceImpl implements IOnlDragExternalService {
//
@Autowired // @Autowired
@Lazy // @Lazy
private BaseCommonService baseCommonService; // private BaseCommonService baseCommonService;
//
@Autowired // @Autowired
@Lazy // @Lazy
private ISysBaseAPI sysBaseApi; // private ISysBaseAPI sysBaseApi;
/** // /**
* 根据多个字典code查询多个字典项 // * 根据多个字典code查询多个字典项
* @param codeList // * @param codeList
* @return key = dictCode value=对应的字典项 // * @return key = dictCode value=对应的字典项
*/ // */
@Override // @Override
public Map<String, List<DragDictModel>> getManyDictItems(List<String> codeList, List<JSONObject> tableDictList) { // public Map<String, List<DragDictModel>> getManyDictItems(List<String> codeList, List<JSONObject> tableDictList) {
Map<String, List<DragDictModel>> manyDragDictItems = new HashMap<>(); // Map<String, List<DragDictModel>> manyDragDictItems = new HashMap<>();
if(!CollectionUtils.isEmpty(codeList)){ // if(!CollectionUtils.isEmpty(codeList)){
Map<String, List<DictModel>> dictItemsMap = sysBaseApi.getManyDictItems(codeList); // Map<String, List<DictModel>> dictItemsMap = sysBaseApi.getManyDictItems(codeList);
dictItemsMap.forEach((k,v)->{ // dictItemsMap.forEach((k,v)->{
List<DragDictModel> dictItems = new ArrayList<>(); // List<DragDictModel> dictItems = new ArrayList<>();
v.forEach(dictItem->{ // v.forEach(dictItem->{
DragDictModel dictModel = new DragDictModel(); // DragDictModel dictModel = new DragDictModel();
BeanUtils.copyProperties(dictItem,dictModel); // BeanUtils.copyProperties(dictItem,dictModel);
dictItems.add(dictModel); // dictItems.add(dictModel);
}); // });
manyDragDictItems.put(k,dictItems); // manyDragDictItems.put(k,dictItems);
}); // });
} // }
//
if(!CollectionUtils.isEmpty(tableDictList)){ // if(!CollectionUtils.isEmpty(tableDictList)){
tableDictList.forEach(item->{ // tableDictList.forEach(item->{
List<DragDictModel> dictItems = new ArrayList<>(); // List<DragDictModel> dictItems = new ArrayList<>();
JSONObject object = JSONObject.parseObject(item.toString()); // JSONObject object = JSONObject.parseObject(item.toString());
String dictField = object.getString("dictField"); // String dictField = object.getString("dictField");
String dictTable = object.getString("dictTable"); // String dictTable = object.getString("dictTable");
String dictText = object.getString("dictText"); // String dictText = object.getString("dictText");
String fieldName = object.getString("fieldName"); // String fieldName = object.getString("fieldName");
List<DictModel> dictItemsList = sysBaseApi.queryTableDictItemsByCode(dictTable,dictText,dictField); // List<DictModel> dictItemsList = sysBaseApi.queryTableDictItemsByCode(dictTable,dictText,dictField);
dictItemsList.forEach(dictItem->{ // dictItemsList.forEach(dictItem->{
DragDictModel dictModel = new DragDictModel(); // DragDictModel dictModel = new DragDictModel();
BeanUtils.copyProperties(dictItem,dictModel); // BeanUtils.copyProperties(dictItem,dictModel);
dictItems.add(dictModel); // dictItems.add(dictModel);
}); // });
manyDragDictItems.put(fieldName,dictItems); // manyDragDictItems.put(fieldName,dictItems);
}); // });
} // }
return manyDragDictItems; // return manyDragDictItems;
} // }
//
/** // /**
* // *
* @param dictCode // * @param dictCode
* @return // * @return
*/ // */
@Override // @Override
public List<DragDictModel> getDictItems(String dictCode) { // public List<DragDictModel> getDictItems(String dictCode) {
List<DragDictModel> dictItems = new ArrayList<>(); // List<DragDictModel> dictItems = new ArrayList<>();
if(oConvertUtils.isNotEmpty(dictCode)){ // if(oConvertUtils.isNotEmpty(dictCode)){
List<DictModel> dictItemsList = sysBaseApi.getDictItems(dictCode); // List<DictModel> dictItemsList = sysBaseApi.getDictItems(dictCode);
dictItemsList.forEach(dictItem->{ // dictItemsList.forEach(dictItem->{
DragDictModel dictModel = new DragDictModel(); // DragDictModel dictModel = new DragDictModel();
BeanUtils.copyProperties(dictItem,dictModel); // BeanUtils.copyProperties(dictItem,dictModel);
dictItems.add(dictModel); // dictItems.add(dictModel);
}); // });
} // }
return dictItems; // return dictItems;
} // }
//
/** // /**
* 添加日志 // * 添加日志
* @param dragLogDTO // * @param dragLogDTO
*/ // */
@Override // @Override
public void addLog(DragLogDTO dragLogDTO) { // public void addLog(DragLogDTO dragLogDTO) {
if(oConvertUtils.isNotEmpty(dragLogDTO)){ // if(oConvertUtils.isNotEmpty(dragLogDTO)){
LogDTO dto = new LogDTO(); // LogDTO dto = new LogDTO();
BeanUtils.copyProperties(dragLogDTO,dto); // BeanUtils.copyProperties(dragLogDTO,dto);
baseCommonService.addLog(dto); // baseCommonService.addLog(dto);
} // }
} // }
//
/** // /**
* 保存日志 // * 保存日志
* @param logMsg // * @param logMsg
* @param logType // * @param logType
* @param operateType // * @param operateType
*/ // */
@Override // @Override
public void addLog(String logMsg, int logType, int operateType) { // public void addLog(String logMsg, int logType, int operateType) {
baseCommonService.addLog(logMsg,logType,operateType); // baseCommonService.addLog(logMsg,logType,operateType);
} // }
} //}

View File

@ -1,107 +1,107 @@
package org.jeecg.config.jimureport; //package org.jeecg.config.jimureport;
//
import lombok.extern.slf4j.Slf4j; //import lombok.extern.slf4j.Slf4j;
import org.jeecg.common.system.util.JwtUtil; //import org.jeecg.common.system.util.JwtUtil;
import org.jeecg.common.system.vo.SysUserCacheInfo; //import org.jeecg.common.system.vo.SysUserCacheInfo;
import org.jeecg.common.util.RedisUtil; //import org.jeecg.common.util.RedisUtil;
import org.jeecg.common.util.TokenUtils; //import org.jeecg.common.util.TokenUtils;
import org.jeecg.modules.jmreport.api.JmReportTokenServiceI; //import org.jeecg.modules.jmreport.api.JmReportTokenServiceI;
import org.jeecg.modules.system.service.impl.SysBaseApiImpl; //import org.jeecg.modules.system.service.impl.SysBaseApiImpl;
import org.springframework.beans.factory.annotation.Autowired; //import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Lazy; //import org.springframework.context.annotation.Lazy;
import org.springframework.stereotype.Component; //import org.springframework.stereotype.Component;
import org.springframework.util.CollectionUtils; //import org.springframework.util.CollectionUtils;
//
import jakarta.servlet.http.HttpServletRequest; //import jakarta.servlet.http.HttpServletRequest;
import java.util.HashMap; //import java.util.HashMap;
import java.util.Map; //import java.util.Map;
import java.util.Set; //import java.util.Set;
//
/** ///**
* 自定义积木报表鉴权(如果不进行自定义,则所有请求不做权限控制) // * 自定义积木报表鉴权(如果不进行自定义,则所有请求不做权限控制)
* * 1.自定义获取登录token // * * 1.自定义获取登录token
* * 2.自定义获取登录用户 // * * 2.自定义获取登录用户
* @author: jeecg-boot // * @author: jeecg-boot
*/ // */
//
//
@Slf4j //@Slf4j
@Component //@Component
public class JimuReportTokenService implements JmReportTokenServiceI { //public class JimuReportTokenService implements JmReportTokenServiceI {
@Autowired // @Autowired
private SysBaseApiImpl sysBaseApi; // private SysBaseApiImpl sysBaseApi;
@Autowired // @Autowired
@Lazy // @Lazy
private RedisUtil redisUtil; // private RedisUtil redisUtil;
//
@Override // @Override
public String getToken(HttpServletRequest request) { // public String getToken(HttpServletRequest request) {
return TokenUtils.getTokenByRequest(request); // return TokenUtils.getTokenByRequest(request);
} // }
//
@Override // @Override
public String getUsername(String token) { // public String getUsername(String token) {
return JwtUtil.getUsername(token); // return JwtUtil.getUsername(token);
} // }
//
@Override // @Override
public String[] getRoles(String token) { // public String[] getRoles(String token) {
String username = JwtUtil.getUsername(token); // String username = JwtUtil.getUsername(token);
Set roles = sysBaseApi.getUserRoleSet(username); // Set roles = sysBaseApi.getUserRoleSet(username);
if(CollectionUtils.isEmpty(roles)){ // if(CollectionUtils.isEmpty(roles)){
return null; // return null;
} // }
return (String[]) roles.toArray(new String[roles.size()]); // return (String[]) roles.toArray(new String[roles.size()]);
} // }
//
@Override // @Override
public Boolean verifyToken(String token) { // public Boolean verifyToken(String token) {
return TokenUtils.verifyToken(token, sysBaseApi, redisUtil); // return TokenUtils.verifyToken(token, sysBaseApi, redisUtil);
} // }
//
@Override // @Override
public Map<String, Object> getUserInfo(String token) { // public Map<String, Object> getUserInfo(String token) {
Map<String, Object> map = new HashMap(5); // Map<String, Object> map = new HashMap(5);
String username = JwtUtil.getUsername(token); // String username = JwtUtil.getUsername(token);
//此处通过token只能拿到一个信息 用户账号 后面的就是根据账号获取其他信息 查询数据或是走redis 用户根据自身业务可自定义 // //此处通过token只能拿到一个信息 用户账号 后面的就是根据账号获取其他信息 查询数据或是走redis 用户根据自身业务可自定义
SysUserCacheInfo userInfo = null; // SysUserCacheInfo userInfo = null;
try { // try {
userInfo = sysBaseApi.getCacheUser(username); // userInfo = sysBaseApi.getCacheUser(username);
} catch (Exception e) { // } catch (Exception e) {
log.error("获取用户信息异常:"+ e.getMessage()); // log.error("获取用户信息异常:"+ e.getMessage());
return map; // return map;
} // }
//设置账号名 // //设置账号名
map.put(SYS_USER_CODE, userInfo.getSysUserCode()); // map.put(SYS_USER_CODE, userInfo.getSysUserCode());
//设置部门编码 // //设置部门编码
map.put(SYS_ORG_CODE, userInfo.getSysOrgCode()); // map.put(SYS_ORG_CODE, userInfo.getSysOrgCode());
// 将所有信息存放至map 解析sql/api会根据map的键值解析 // // 将所有信息存放至map 解析sql/api会根据map的键值解析
return map; // return map;
} // }
//
/** // /**
* 将jeecgboot平台的权限传递给积木报表 // * 将jeecgboot平台的权限传递给积木报表
* @param token // * @param token
* @return // * @return
*/ // */
@Override // @Override
public String[] getPermissions(String token) { // public String[] getPermissions(String token) {
// 获取用户信息 // // 获取用户信息
String username = JwtUtil.getUsername(token); // String username = JwtUtil.getUsername(token);
SysUserCacheInfo userInfo = null; // SysUserCacheInfo userInfo = null;
try { // try {
userInfo = sysBaseApi.getCacheUser(username); // userInfo = sysBaseApi.getCacheUser(username);
} catch (Exception e) { // } catch (Exception e) {
log.error("获取用户信息异常:"+ e.getMessage()); // log.error("获取用户信息异常:"+ e.getMessage());
} // }
if(userInfo == null){ // if(userInfo == null){
return null; // return null;
} // }
// 查询权限 // // 查询权限
Set<String> userPermissions = sysBaseApi.getUserPermissionSet(userInfo.getSysUserId()); // Set<String> userPermissions = sysBaseApi.getUserPermissionSet(userInfo.getSysUserId());
if(CollectionUtils.isEmpty(userPermissions)){ // if(CollectionUtils.isEmpty(userPermissions)){
return null; // return null;
} // }
return userPermissions.toArray(new String[0]); // return userPermissions.toArray(new String[0]);
} // }
} //}

View File

@ -1,64 +1,56 @@
////
//// Source code recreated from a .class file by IntelliJ IDEA
//// (powered by Fernflower decompiler)
////
// //
// Source code recreated from a .class file by IntelliJ IDEA //package org.springframework.boot.autoconfigure.mongo;
// (powered by Fernflower decompiler)
// //
//import com.mongodb.MongoClientSettings;
package org.springframework.boot.autoconfigure.mongo; //import com.mongodb.client.MongoClient;
//import org.springframework.beans.factory.ObjectProvider;
import com.mongodb.MongoClientSettings; //import org.springframework.boot.autoconfigure.AutoConfiguration;
import com.mongodb.client.MongoClient; //import org.springframework.boot.autoconfigure.condition.ConditionalOnClass;
import org.springframework.beans.factory.ObjectProvider; //import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
import org.springframework.boot.autoconfigure.AutoConfiguration; //import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
import org.springframework.boot.autoconfigure.condition.ConditionalOnClass; //import org.springframework.boot.context.properties.EnableConfigurationProperties;
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean; //import org.springframework.context.annotation.Bean;
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty; //import org.springframework.context.annotation.Configuration;
import org.springframework.boot.autoconfigure.mongo.MongoClientFactory; //import org.springframework.context.annotation.Primary;
import org.springframework.boot.autoconfigure.mongo.MongoClientSettingsBuilderCustomizer; //import org.springframework.core.env.Environment;
import org.springframework.boot.autoconfigure.mongo.MongoProperties; //
import org.springframework.boot.autoconfigure.mongo.MongoPropertiesClientSettingsBuilderCustomizer; //import java.util.List;
import org.springframework.boot.context.properties.EnableConfigurationProperties; //import java.util.stream.Collectors;
import org.springframework.context.annotation.Bean; //
import org.springframework.context.annotation.Configuration; //@Primary
import org.springframework.context.annotation.Primary; //@AutoConfiguration
import org.springframework.core.env.Environment; //@ConditionalOnClass({MongoClient.class})
//@ConditionalOnProperty(name = "spring.data.mongodb.uri", havingValue = "", matchIfMissing = false)
import java.util.List; //@EnableConfigurationProperties({MongoProperties.class})
import java.util.stream.Collectors; //@ConditionalOnMissingBean(
// type = {"org.springframework.data.mongodb.MongoDatabaseFactory"}
@Primary //)
@AutoConfiguration //public class MongoAutoConfiguration {
@ConditionalOnClass({MongoClient.class}) // public MongoAutoConfiguration() {
@ConditionalOnProperty(name = "spring.data.mongodb.uri", havingValue = "", matchIfMissing = false) // }
@EnableConfigurationProperties({MongoProperties.class}) //
@ConditionalOnMissingBean( // @Bean
type = {"org.springframework.data.mongodb.MongoDatabaseFactory"} // @ConditionalOnMissingBean({MongoClient.class})
) // public MongoClient mongo(ObjectProvider<MongoClientSettingsBuilderCustomizer> builderCustomizers, MongoClientSettings settings) {
public class MongoAutoConfiguration { // return (MongoClient)(new MongoClientFactory((List)builderCustomizers.orderedStream().collect(Collectors.toList()))).createMongoClient(settings);
public MongoAutoConfiguration() { // }
} //
// @Configuration(
@Bean // proxyBeanMethods = false
@ConditionalOnMissingBean({MongoClient.class}) // )
public MongoClient mongo(ObjectProvider<MongoClientSettingsBuilderCustomizer> builderCustomizers, MongoClientSettings settings) { // @ConditionalOnMissingBean({MongoClientSettings.class})
return (MongoClient)(new MongoClientFactory((List)builderCustomizers.orderedStream().collect(Collectors.toList()))).createMongoClient(settings); // static class MongoClientSettingsConfiguration {
} // MongoClientSettingsConfiguration() {
// }
@Configuration( //
proxyBeanMethods = false // @Bean
) // MongoClientSettings mongoClientSettings() {
@ConditionalOnMissingBean({MongoClientSettings.class}) // return MongoClientSettings.builder().build();
static class MongoClientSettingsConfiguration { // }
MongoClientSettingsConfiguration() { //
} // }
//}
@Bean
MongoClientSettings mongoClientSettings() {
return MongoClientSettings.builder().build();
}
@Bean
MongoPropertiesClientSettingsBuilderCustomizer mongoPropertiesCustomizer(MongoProperties properties, Environment environment) {
return new MongoPropertiesClientSettingsBuilderCustomizer(properties);
}
}
}

View File

@ -23,7 +23,7 @@
<parent> <parent>
<groupId>org.springframework.boot</groupId> <groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId> <artifactId>spring-boot-starter-parent</artifactId>
<version>3.1.5</version> <version>3.4.4</version>
<relativePath/> <relativePath/>
</parent> </parent>
@ -33,8 +33,8 @@
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding> <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<!-- 微服务 --> <!-- 微服务 -->
<spring-cloud.version>2022.0.4</spring-cloud.version> <spring-cloud.version>2024.0.1</spring-cloud.version>
<spring-cloud-alibaba.version>2022.0.0.0</spring-cloud-alibaba.version> <spring-cloud-alibaba.version>2023.0.3.2</spring-cloud-alibaba.version>
<alibaba.nacos.version>2.0.4</alibaba.nacos.version> <alibaba.nacos.version>2.0.4</alibaba.nacos.version>
<xxl-job-core.version>2.4.1</xxl-job-core.version> <xxl-job-core.version>2.4.1</xxl-job-core.version>
@ -56,7 +56,7 @@
<!-- 积木报表--> <!-- 积木报表-->
<jimureport-spring-boot-starter.version>1.9.4</jimureport-spring-boot-starter.version> <jimureport-spring-boot-starter.version>1.9.4</jimureport-spring-boot-starter.version>
<!-- 持久层 --> <!-- 持久层 -->
<mybatis-plus.version>3.5.3.2</mybatis-plus.version> <mybatis-plus.version>3.5.11</mybatis-plus.version>
<dynamic-datasource-spring-boot-starter.version>4.1.3</dynamic-datasource-spring-boot-starter.version> <dynamic-datasource-spring-boot-starter.version>4.1.3</dynamic-datasource-spring-boot-starter.version>
<druid.version>1.2.24</druid.version> <druid.version>1.2.24</druid.version>
@ -79,7 +79,7 @@
<!-- Log4j2爆雷漏洞 --> <!-- Log4j2爆雷漏洞 -->
<!-- spring boot 3 不支持下列两个版本--> <!-- spring boot 3 不支持下列两个版本-->
<!--<log4j2.version>2.17.0</log4j2.version>--> <!--<log4j2.version>2.17.0</log4j2.version>-->
<logback.version>1.4.12</logback.version> <!--<logback.version>1.4.12</logback.version>-->
</properties> </properties>
<modules> <modules>