mirror of
https://gitee.com/best_handsome/mybatis-plus-join
synced 2025-07-11 00:02:22 +08:00
同步 MP 3.5.3.2 sql注入检查代码
https://gitee.com/baomidou/mybatis-plus/issues/I7OCM4
This commit is contained in:
parent
026c64ee59
commit
a8b91edb6b
@ -7,12 +7,15 @@ import com.baomidou.mybatisplus.core.conditions.interfaces.Nested;
|
||||
import com.baomidou.mybatisplus.core.conditions.segments.MergeSegments;
|
||||
import com.baomidou.mybatisplus.core.enums.SqlKeyword;
|
||||
import com.baomidou.mybatisplus.core.enums.SqlLike;
|
||||
import com.baomidou.mybatisplus.core.exceptions.MybatisPlusException;
|
||||
import com.baomidou.mybatisplus.core.toolkit.*;
|
||||
import com.baomidou.mybatisplus.core.toolkit.sql.SqlUtils;
|
||||
import com.baomidou.mybatisplus.core.toolkit.sql.StringEscape;
|
||||
import com.github.yulichang.kt.interfaces.*;
|
||||
import com.github.yulichang.kt.interfaces.Compare;
|
||||
import com.github.yulichang.kt.interfaces.Func;
|
||||
import com.github.yulichang.kt.interfaces.OnCompare;
|
||||
import com.github.yulichang.toolkit.KtUtils;
|
||||
import com.github.yulichang.toolkit.MPJStringUtils;
|
||||
import com.github.yulichang.toolkit.MPJSqlInjectionUtils;
|
||||
import com.github.yulichang.toolkit.TableList;
|
||||
import com.github.yulichang.toolkit.sql.SqlScriptUtils;
|
||||
import com.github.yulichang.wrapper.enums.PrefixEnum;
|
||||
@ -110,6 +113,11 @@ public abstract class KtAbstractWrapper<T, Children extends KtAbstractWrapper<T,
|
||||
@Getter
|
||||
protected TableList tableList;
|
||||
|
||||
/**
|
||||
* 检查 SQL 注入过滤
|
||||
*/
|
||||
protected boolean checkSqlInjection = false;
|
||||
|
||||
@Override
|
||||
public T getEntity() {
|
||||
return entity;
|
||||
@ -138,8 +146,16 @@ public abstract class KtAbstractWrapper<T, Children extends KtAbstractWrapper<T,
|
||||
return typedThis;
|
||||
}
|
||||
|
||||
/**
|
||||
* 开启检查 SQL 注入
|
||||
*/
|
||||
public Children checkSqlInjection() {
|
||||
this.checkSqlInjection = true;
|
||||
return typedThis;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Children allEq(boolean condition, Map<KProperty<?>, ?> params, boolean null2IsNull) {
|
||||
public Children allEq(boolean condition, Map<KProperty<?>, ?> params, boolean null2IsNull) {
|
||||
if (condition && CollectionUtils.isNotEmpty(params)) {
|
||||
params.forEach((k, v) -> {
|
||||
if (StringUtils.checkValNotNull(v)) {
|
||||
@ -155,17 +171,17 @@ public abstract class KtAbstractWrapper<T, Children extends KtAbstractWrapper<T,
|
||||
}
|
||||
|
||||
@Override
|
||||
public Children eq(boolean condition, KProperty<?> column, Object val) {
|
||||
public Children eq(boolean condition, KProperty<?> column, Object val) {
|
||||
return addCondition(condition, column, EQ, val);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Children ne(boolean condition, KProperty<?> column, Object val) {
|
||||
public Children ne(boolean condition, KProperty<?> column, Object val) {
|
||||
return addCondition(condition, column, NE, val);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Children gt(boolean condition, KProperty<?> column, Object val) {
|
||||
public Children gt(boolean condition, KProperty<?> column, Object val) {
|
||||
return addCondition(condition, column, GT, val);
|
||||
}
|
||||
|
||||
@ -175,27 +191,27 @@ public abstract class KtAbstractWrapper<T, Children extends KtAbstractWrapper<T,
|
||||
}
|
||||
|
||||
@Override
|
||||
public Children lt(boolean condition, KProperty<?> column, Object val) {
|
||||
public Children lt(boolean condition, KProperty<?> column, Object val) {
|
||||
return addCondition(condition, column, LT, val);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Children le(boolean condition, KProperty<?> column, Object val) {
|
||||
public Children le(boolean condition, KProperty<?> column, Object val) {
|
||||
return addCondition(condition, column, LE, val);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Children like(boolean condition, KProperty<?> column, Object val) {
|
||||
public Children like(boolean condition, KProperty<?> column, Object val) {
|
||||
return likeValue(condition, LIKE, column, val, SqlLike.DEFAULT);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Children notLike(boolean condition, KProperty<?> column, Object val) {
|
||||
public Children notLike(boolean condition, KProperty<?> column, Object val) {
|
||||
return likeValue(condition, NOT_LIKE, column, val, SqlLike.DEFAULT);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Children likeLeft(boolean condition, KProperty<?> column, Object val) {
|
||||
public Children likeLeft(boolean condition, KProperty<?> column, Object val) {
|
||||
return likeValue(condition, LIKE, column, val, SqlLike.LEFT);
|
||||
}
|
||||
|
||||
@ -205,13 +221,13 @@ public abstract class KtAbstractWrapper<T, Children extends KtAbstractWrapper<T,
|
||||
}
|
||||
|
||||
@Override
|
||||
public Children between(boolean condition, KProperty<?> column, Object val1, Object val2) {
|
||||
public Children between(boolean condition, KProperty<?> column, Object val1, Object val2) {
|
||||
return maybeDo(condition, () -> appendSqlSegments(columnToSqlSegment(index, column, false), BETWEEN,
|
||||
() -> formatParam(null, val1), AND, () -> formatParam(null, val2)));
|
||||
}
|
||||
|
||||
@Override
|
||||
public Children notBetween(boolean condition, KProperty<?> column, Object val1, Object val2) {
|
||||
public Children notBetween(boolean condition, KProperty<?> column, Object val1, Object val2) {
|
||||
return maybeDo(condition, () -> appendSqlSegments(columnToSqlSegment(index, column, false), NOT_BETWEEN,
|
||||
() -> formatParam(null, val1), AND, () -> formatParam(null, val2)));
|
||||
}
|
||||
@ -283,7 +299,7 @@ public abstract class KtAbstractWrapper<T, Children extends KtAbstractWrapper<T,
|
||||
}
|
||||
|
||||
@Override
|
||||
public Children isNull(boolean condition, KProperty<?> column) {
|
||||
public Children isNull(boolean condition, KProperty<?> column) {
|
||||
return maybeDo(condition, () -> appendSqlSegments(columnToSqlSegment(index, column, false), IS_NULL));
|
||||
}
|
||||
|
||||
@ -677,7 +693,7 @@ public abstract class KtAbstractWrapper<T, Children extends KtAbstractWrapper<T,
|
||||
}
|
||||
|
||||
protected final ISqlSegment columnToSqlSegment(String column) {
|
||||
return () -> (String) column;
|
||||
return () -> columnsToString(column);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -688,6 +704,9 @@ public abstract class KtAbstractWrapper<T, Children extends KtAbstractWrapper<T,
|
||||
}
|
||||
|
||||
protected String columnToString(String column) {
|
||||
if (checkSqlInjection && MPJSqlInjectionUtils.check(column)) {
|
||||
throw new MybatisPlusException("Discovering SQL injection column: " + column);
|
||||
}
|
||||
return column;
|
||||
}
|
||||
|
||||
@ -941,18 +960,14 @@ public abstract class KtAbstractWrapper<T, Children extends KtAbstractWrapper<T,
|
||||
public final Children orderBy(boolean condition, boolean isAsc, String column, String... columns) {
|
||||
return maybeDo(condition, () -> {
|
||||
final SqlKeyword mode = isAsc ? ASC : DESC;
|
||||
appendSqlSegments(ORDER_BY, columnToSqlSegment(columnSqlInjectFilter(column)), mode);
|
||||
appendSqlSegments(ORDER_BY, columnToSqlSegment(column), mode);
|
||||
if (ArrayUtils.isNotEmpty(columns)) {
|
||||
Arrays.stream(columns).forEach(c -> appendSqlSegments(ORDER_BY,
|
||||
columnToSqlSegment(columnSqlInjectFilter(c)), mode));
|
||||
columnToSqlSegment(c), mode));
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
protected String columnSqlInjectFilter(String column) {
|
||||
return MPJStringUtils.sqlInjectionReplaceBlank(column);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Children groupBy(boolean condition, String column) {
|
||||
return maybeDo(condition, () -> appendSqlSegments(GROUP_BY, () -> columnToString(column)));
|
||||
@ -965,13 +980,13 @@ public abstract class KtAbstractWrapper<T, Children extends KtAbstractWrapper<T,
|
||||
|
||||
@Override
|
||||
public Children orderBy(boolean condition, boolean isAsc, String column) {
|
||||
return maybeDo(condition, () -> appendSqlSegments(ORDER_BY, columnToSqlSegment(columnSqlInjectFilter(column)),
|
||||
return maybeDo(condition, () -> appendSqlSegments(ORDER_BY, columnToSqlSegment(column),
|
||||
isAsc ? ASC : DESC));
|
||||
}
|
||||
|
||||
@Override
|
||||
public Children orderByStr(boolean condition, boolean isAsc, List<String> columns) {
|
||||
return maybeDo(condition, () -> columns.forEach(c -> appendSqlSegments(ORDER_BY,
|
||||
columnToSqlSegment(columnSqlInjectFilter(c)), isAsc ? ASC : DESC)));
|
||||
columnToSqlSegment(c), isAsc ? ASC : DESC)));
|
||||
}
|
||||
}
|
||||
|
@ -30,11 +30,12 @@ public class MPJSqlInjectionUtils {
|
||||
* SQL语法检查正则:符合两个关键字(有先后顺序)才算匹配
|
||||
*/
|
||||
private static final Pattern SQL_SYNTAX_PATTERN = Pattern.compile("(insert|delete|update|select|create|drop|truncate|grant|alter|deny|revoke|call|execute|exec|declare|show|rename|set)" +
|
||||
"\\s+.*(into|from|set|where|table|database|view|index|on|cursor|procedure|trigger|for|password|union|and|or)|(select\\s*\\*\\s*from\\s+)", Pattern.CASE_INSENSITIVE);
|
||||
"\\s+.*(into|from|set|where|table|database|view|index|on|cursor|procedure|trigger|for|password|union|and|or)|(select\\s*\\*\\s*from\\s+)|(and|or)\\s+.*(like|=|>|<|in|between|is|not|exists)", Pattern.CASE_INSENSITIVE);
|
||||
/**
|
||||
* 使用'、;或注释截断SQL检查正则
|
||||
*/
|
||||
private static final Pattern SQL_COMMENT_PATTERN = Pattern.compile("'.*(or|union|--|#|/*|;)", Pattern.CASE_INSENSITIVE);
|
||||
private static final Pattern SQL_COMMENT_PATTERN = Pattern.compile("'.*(or|union|--|#|/\\*|;)", Pattern.CASE_INSENSITIVE);
|
||||
|
||||
|
||||
/**
|
||||
* 检查参数是否存在 SQL 注入
|
||||
|
@ -16,6 +16,7 @@ import java.util.Optional;
|
||||
* @author yulichang
|
||||
* @since 1.4.5
|
||||
*/
|
||||
@SuppressWarnings("DuplicatedCode")
|
||||
public class WrapperUtils {
|
||||
|
||||
public static <T> String buildSubSqlByWrapper(Class<T> clazz, MPJLambdaWrapper<T> wrapper, String alias) {
|
||||
|
@ -7,12 +7,13 @@ import com.baomidou.mybatisplus.core.conditions.interfaces.Nested;
|
||||
import com.baomidou.mybatisplus.core.conditions.segments.MergeSegments;
|
||||
import com.baomidou.mybatisplus.core.enums.SqlKeyword;
|
||||
import com.baomidou.mybatisplus.core.enums.SqlLike;
|
||||
import com.baomidou.mybatisplus.core.exceptions.MybatisPlusException;
|
||||
import com.baomidou.mybatisplus.core.toolkit.*;
|
||||
import com.baomidou.mybatisplus.core.toolkit.sql.SqlUtils;
|
||||
import com.baomidou.mybatisplus.core.toolkit.sql.StringEscape;
|
||||
import com.baomidou.mybatisplus.core.toolkit.support.SFunction;
|
||||
import com.github.yulichang.toolkit.LambdaUtils;
|
||||
import com.github.yulichang.toolkit.MPJStringUtils;
|
||||
import com.github.yulichang.toolkit.MPJSqlInjectionUtils;
|
||||
import com.github.yulichang.toolkit.TableList;
|
||||
import com.github.yulichang.toolkit.sql.SqlScriptUtils;
|
||||
import com.github.yulichang.wrapper.enums.PrefixEnum;
|
||||
@ -107,6 +108,11 @@ public abstract class MPJAbstractWrapper<T, Children extends MPJAbstractWrapper<
|
||||
@Getter
|
||||
protected TableList tableList;
|
||||
|
||||
/**
|
||||
* 检查 SQL 注入过滤
|
||||
*/
|
||||
protected boolean checkSqlInjection = false;
|
||||
|
||||
@Override
|
||||
public T getEntity() {
|
||||
return entity;
|
||||
@ -135,6 +141,14 @@ public abstract class MPJAbstractWrapper<T, Children extends MPJAbstractWrapper<
|
||||
return typedThis;
|
||||
}
|
||||
|
||||
/**
|
||||
* 开启检查 SQL 注入
|
||||
*/
|
||||
public Children checkSqlInjection() {
|
||||
this.checkSqlInjection = true;
|
||||
return typedThis;
|
||||
}
|
||||
|
||||
@Override
|
||||
public <X, V> Children allEq(boolean condition, Map<SFunction<X, ?>, V> params, boolean null2IsNull) {
|
||||
if (condition && CollectionUtils.isNotEmpty(params)) {
|
||||
@ -692,7 +706,7 @@ public abstract class MPJAbstractWrapper<T, Children extends MPJAbstractWrapper<
|
||||
}
|
||||
|
||||
protected final <X> ISqlSegment columnToSqlSegment(String column) {
|
||||
return () -> (String) column;
|
||||
return () -> columnsToString(column);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -703,6 +717,9 @@ public abstract class MPJAbstractWrapper<T, Children extends MPJAbstractWrapper<
|
||||
}
|
||||
|
||||
protected String columnToString(String column) {
|
||||
if (checkSqlInjection && MPJSqlInjectionUtils.check(column)) {
|
||||
throw new MybatisPlusException("Discovering SQL injection column: " + column);
|
||||
}
|
||||
return column;
|
||||
}
|
||||
|
||||
@ -956,18 +973,14 @@ public abstract class MPJAbstractWrapper<T, Children extends MPJAbstractWrapper<
|
||||
public final Children orderBy(boolean condition, boolean isAsc, String column, String... columns) {
|
||||
return maybeDo(condition, () -> {
|
||||
final SqlKeyword mode = isAsc ? ASC : DESC;
|
||||
appendSqlSegments(ORDER_BY, columnToSqlSegment(columnSqlInjectFilter(column)), mode);
|
||||
appendSqlSegments(ORDER_BY, columnToSqlSegment(column), mode);
|
||||
if (ArrayUtils.isNotEmpty(columns)) {
|
||||
Arrays.stream(columns).forEach(c -> appendSqlSegments(ORDER_BY,
|
||||
columnToSqlSegment(columnSqlInjectFilter(c)), mode));
|
||||
columnToSqlSegment(c), mode));
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
protected String columnSqlInjectFilter(String column) {
|
||||
return MPJStringUtils.sqlInjectionReplaceBlank(column);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Children groupBy(boolean condition, String column) {
|
||||
return maybeDo(condition, () -> appendSqlSegments(GROUP_BY, () -> columnToString(column)));
|
||||
@ -980,13 +993,13 @@ public abstract class MPJAbstractWrapper<T, Children extends MPJAbstractWrapper<
|
||||
|
||||
@Override
|
||||
public Children orderBy(boolean condition, boolean isAsc, String column) {
|
||||
return maybeDo(condition, () -> appendSqlSegments(ORDER_BY, columnToSqlSegment(columnSqlInjectFilter(column)),
|
||||
return maybeDo(condition, () -> appendSqlSegments(ORDER_BY, columnToSqlSegment(column),
|
||||
isAsc ? ASC : DESC));
|
||||
}
|
||||
|
||||
@Override
|
||||
public Children orderByStr(boolean condition, boolean isAsc, List<String> columns) {
|
||||
return maybeDo(condition, () -> columns.forEach(c -> appendSqlSegments(ORDER_BY,
|
||||
columnToSqlSegment(columnSqlInjectFilter(c)), isAsc ? ASC : DESC)));
|
||||
columnToSqlSegment(c), isAsc ? ASC : DESC)));
|
||||
}
|
||||
}
|
||||
|
@ -57,7 +57,6 @@ public class MPJLambdaWrapper<T> extends MPJAbstractLambdaWrapper<T, MPJLambdaWr
|
||||
*/
|
||||
private SharedString unionSql;
|
||||
|
||||
|
||||
/**
|
||||
* 推荐使用 带 class 的构造方法
|
||||
*/
|
||||
|
Loading…
x
Reference in New Issue
Block a user